的
@@ -0,0 +1 @@
|
||||
/build
|
||||
@@ -0,0 +1,144 @@
|
||||
apply plugin: 'com.android.application'
|
||||
|
||||
/**获取git count HEAD,可以根据该值回退版本*/
|
||||
def getMyVersionCode() {
|
||||
Process process = "git rev-list --count HEAD".execute()
|
||||
process.waitFor()
|
||||
int cccc = process.getText().toInteger()
|
||||
return cccc
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 28
|
||||
defaultConfig {
|
||||
applicationId "com.tophold.example"
|
||||
minSdkVersion 17
|
||||
targetSdkVersion 28
|
||||
versionCode getMyVersionCode() as int//查询versioncode即可找到对应git历史
|
||||
versionName "0.0.1"
|
||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||
|
||||
|
||||
}
|
||||
|
||||
signingConfigs {
|
||||
//debug模式下签名的设置,这里的配置主要用于脚本运行。对于采用图形界面构建测不起效。
|
||||
debug {
|
||||
storeFile file(project.debug_storeFile)
|
||||
storePassword project.debug_storePassword
|
||||
keyAlias project.debug_keyAlias
|
||||
keyPassword project.debug_keyPassword
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
|
||||
beta {
|
||||
storeFile file(project.debug_storeFile)
|
||||
storePassword project.debug_storePassword
|
||||
keyAlias project.debug_keyAlias
|
||||
keyPassword project.debug_keyPassword
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
|
||||
release {
|
||||
storeFile file(project.release_storeFile)
|
||||
storePassword project.release_storePassword
|
||||
keyAlias project.release_keyAlias
|
||||
keyPassword project.release_keyPassword
|
||||
v1SigningEnabled true
|
||||
v2SigningEnabled true
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
//平时开发使用
|
||||
debug {
|
||||
// 显示Log
|
||||
buildConfigField "boolean", "LOG_DEBUG", "true"
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
zipAlignEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
//versionName的后缀
|
||||
versionNameSuffix "_debug"
|
||||
//appId后缀,加一个后缀保证各个版本(debug、beta、release可以共存)
|
||||
applicationIdSuffix ".debug"
|
||||
//签名选择
|
||||
signingConfig signingConfigs.debug
|
||||
//动态修改应用的名字和图标
|
||||
manifestPlaceholders = [app_names: "金融View_debug"]
|
||||
debuggable true
|
||||
}
|
||||
|
||||
//内侧使用
|
||||
beta {
|
||||
// 显示Log
|
||||
buildConfigField "boolean", "LOG_DEBUG", "true"
|
||||
shrinkResources false
|
||||
minifyEnabled false
|
||||
zipAlignEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
//versionName的后缀
|
||||
versionNameSuffix "_beta"
|
||||
//appId后缀
|
||||
applicationIdSuffix ".beta"
|
||||
//签名选择
|
||||
signingConfig signingConfigs.beta
|
||||
manifestPlaceholders = [app_names: "金融View_beta"]
|
||||
debuggable true
|
||||
}
|
||||
|
||||
//正式版本
|
||||
release {
|
||||
//不显示log信息
|
||||
buildConfigField "boolean", "LOG_DEBUG", "false"
|
||||
// 移除无用的resource文件
|
||||
shrinkResources true
|
||||
//混淆
|
||||
minifyEnabled true
|
||||
//压缩
|
||||
zipAlignEnabled true
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
//签名
|
||||
signingConfig signingConfigs.release
|
||||
|
||||
manifestPlaceholders = [app_names: "金融View"]
|
||||
debuggable true
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'com.android.support:support-v4:28.0.0'
|
||||
implementation 'com.android.support:recyclerview-v7:28.0.0'
|
||||
implementation 'com.android.support:design:28.0.0'
|
||||
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
|
||||
testImplementation 'junit:junit:4.12'
|
||||
androidTestImplementation 'com.android.support.test:runner:1.0.2'
|
||||
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
|
||||
|
||||
implementation project(path: ':financiallib')
|
||||
|
||||
//rx2.0
|
||||
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
|
||||
implementation 'io.reactivex.rxjava2:rxjava:2.2.8'
|
||||
//api
|
||||
implementation 'com.squareup.retrofit2:retrofit:2.5.0'
|
||||
implementation 'com.squareup.retrofit2:converter-gson:2.5.0'
|
||||
implementation 'com.squareup.retrofit2:adapter-rxjava2:2.5.0'
|
||||
implementation 'com.squareup.okhttp3:okhttp:3.12.0'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor:3.11.0'
|
||||
/**https://github.com/CymChad/BaseRecyclerViewAdapterHelper:qucik recycle*/
|
||||
implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.49'
|
||||
implementation 'org.greenrobot:eventbus:3.1.1'
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlin-android-extensions'
|
||||
@@ -0,0 +1,287 @@
|
||||
|
||||
|
||||
|
||||
|
||||
###########################正文####################################
|
||||
##这里是APP默认的混淆配置规则,和第三方没有关系。
|
||||
##这里禁止配置个性化、第三方库的混淆配置。
|
||||
##应用第三方库混淆规则配置请配置在最下方"其它第三方"模块。
|
||||
|
||||
#指定代码的压缩级别
|
||||
-optimizationpasses 5
|
||||
|
||||
#包明不混合大小写
|
||||
-dontusemixedcaseclassnames
|
||||
|
||||
#不去忽略非公共的库类
|
||||
-dontskipnonpubliclibraryclasses
|
||||
|
||||
#优化 不优化输入的类文件
|
||||
-dontoptimize
|
||||
|
||||
#预校验
|
||||
-dontpreverify
|
||||
|
||||
#混淆时是否记录日志
|
||||
-verbose
|
||||
|
||||
# 混淆时所采用的算法
|
||||
-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
|
||||
|
||||
#保护注解
|
||||
-keepattributes *Annotation*
|
||||
|
||||
# 保持哪些类不被混淆
|
||||
-keep public class * extends android.app.Fragment
|
||||
-keep public class * extends android.app.Activity
|
||||
-keep public class * extends android.app.Application
|
||||
-keep public class * extends android.app.Service
|
||||
-keep public class * extends android.content.BroadcastReceiver
|
||||
-keep public class * extends android.content.ContentProvider
|
||||
-keep public class * extends android.app.backup.BackupAgentHelper
|
||||
-keep public class * extends android.preference.Preference
|
||||
-keep public class com.android.vending.licensing.ILicensingService
|
||||
|
||||
#如果引用了v4或者v7包
|
||||
-dontwarn android.support.**
|
||||
|
||||
# support design
|
||||
#@link http://stackoverflow.com/a/31028536
|
||||
-dontwarn android.support.design.**
|
||||
-keep class android.support.design.** { *; }
|
||||
-keep interface android.support.design.** { *; }
|
||||
-keep public class android.support.design.R$* { *; }
|
||||
|
||||
|
||||
#忽略警告
|
||||
-ignorewarning
|
||||
|
||||
##记录生成的日志数据,gradle build时在本项目根目录输出##
|
||||
#apk 包内所有 class 的内部结构
|
||||
-dump proguard/class_files.txt
|
||||
#未混淆的类和成员
|
||||
-printseeds proguard/seeds.txt
|
||||
#列出从 apk 中删除的代码
|
||||
-printusage proguard/unused.txt
|
||||
#混淆前后的映射
|
||||
-printmapping proguard/mapping.txt
|
||||
|
||||
#保持 native 方法不被混淆
|
||||
-keepclasseswithmembernames class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
#保持自定义控件类不被混淆
|
||||
-keepclasseswithmembers class * {
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
}
|
||||
-keepclassmembers class * extends android.app.Activity {
|
||||
public void *(android.view.View);
|
||||
}
|
||||
|
||||
-keep public class * extends android.view.View {
|
||||
public <init>(android.content.Context);
|
||||
public <init>(android.content.Context, android.util.AttributeSet);
|
||||
public <init>(android.content.Context, android.util.AttributeSet, int);
|
||||
public void set*(...);
|
||||
}
|
||||
|
||||
#保持 Parcelable 不被混淆
|
||||
-keep class * implements android.os.Parcelable {
|
||||
public static final android.os.Parcelable$Creator *;
|
||||
}
|
||||
|
||||
#保持 Serializable 不被混淆
|
||||
-keepnames class * implements java.io.Serializable
|
||||
|
||||
#保持 Serializable 不被混淆并且enum 类也不被混淆
|
||||
-keepclassmembers class * implements java.io.Serializable {
|
||||
static final long serialVersionUID;
|
||||
private static final java.io.ObjectStreamField[] serialPersistentFields;
|
||||
!static !transient <fields>;
|
||||
!private <fields>;
|
||||
!private <methods>;
|
||||
private void writeObject(java.io.ObjectOutputStream);
|
||||
private void readObject(java.io.ObjectInputStream);
|
||||
java.lang.Object writeReplace();
|
||||
java.lang.Object readResolve();
|
||||
}
|
||||
|
||||
#保持枚举 enum 类不被混淆
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
-keepclassmembers class * {
|
||||
public void *ButtonClicked(android.view.View);
|
||||
}
|
||||
|
||||
#不混淆资源类
|
||||
-keepclassmembers class **.R$* {
|
||||
public static <fields>;
|
||||
}
|
||||
|
||||
#避免混淆泛型 如果混淆报错建议关掉
|
||||
-keepattributes Signature
|
||||
|
||||
#移除Log类打印各个等级日志的代码,打正式包的时候可以做为禁log使用,这里可以作为禁止log打印的功能使用,另外的一种实现方案是通过BuildConfig.DEBUG的变量来控制
|
||||
#-assumenosideeffects class android.util.Log {
|
||||
# public static *** v(...);
|
||||
# public static *** i(...);
|
||||
# public static *** d(...);
|
||||
# public static *** w(...);
|
||||
# public static *** e(...);
|
||||
#}
|
||||
|
||||
|
||||
|
||||
#################################################必备开发第三方################################
|
||||
# UI相关
|
||||
## https://github.com/JakeWharton/butterknife:butterknife
|
||||
-keep class butterknife.** { *; }
|
||||
-dontwarn butterknife.internal.**
|
||||
-keep class **$$ViewBinder { *; }
|
||||
-keepclasseswithmembernames class * {
|
||||
@butterknife.* <fields>;
|
||||
}
|
||||
-keepclasseswithmembernames class * {
|
||||
@butterknife.* <methods>;
|
||||
}
|
||||
|
||||
## https://github.com/bumptech/glide:glide
|
||||
-keep public class * implements com.bumptech.glide.module.GlideModule
|
||||
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
|
||||
**[] $VALUES;
|
||||
public *;
|
||||
}
|
||||
|
||||
## https://github.com/CymChad/BaseRecyclerViewAdapterHelper:recycle封装
|
||||
-keep class com.chad.library.adapter.** {
|
||||
*;
|
||||
}
|
||||
-keep public class * extends com.chad.library.adapter.base.BaseQuickAdapter
|
||||
-keep public class * extends com.chad.library.adapter.base.BaseViewHolder
|
||||
-keepclassmembers class **$** extends com.chad.library.adapter.base.BaseViewHolder {
|
||||
<init>(...);
|
||||
}
|
||||
|
||||
## https://github.com/gyf-dev/ImmersionBarw:沉浸式*/
|
||||
-keep class com.gyf.barlibrary.* {*;}
|
||||
|
||||
|
||||
# 数据相关
|
||||
## https://github.com/greenrobot/EventBus:EventBus3.0混淆配置
|
||||
-keepattributes *Annotation*
|
||||
-keepclassmembers class ** {
|
||||
@org.greenrobot.eventbus.Subscribe <methods>;
|
||||
}
|
||||
-keep enum org.greenrobot.eventbus.ThreadMode { *; }
|
||||
|
||||
# Only required if you use AsyncExecutor
|
||||
-keepclassmembers class * extends org.greenrobot.eventbus.util.ThrowableFailureEvent {
|
||||
<init>(java.lang.Throwable);
|
||||
}
|
||||
|
||||
## https://github.com/google/gson:gson
|
||||
-keepattributes Signature
|
||||
# Gson specific classes
|
||||
-keep class sun.misc.Unsafe { *; }
|
||||
# Application classes that will be serialized/deserialized over Gson
|
||||
-keep class com.google.gson.** { *; }
|
||||
-keep class com.google.gson.stream.** { *; }
|
||||
|
||||
## https://github.com/Blankj/AndroidUtilCode:安卓开发常用工具类
|
||||
-keep class com.blankj.utilcode.** { *; }
|
||||
-keepclassmembers class com.blankj.utilcode.** { *; }
|
||||
-dontwarn com.blankj.utilcode.**
|
||||
|
||||
|
||||
# APP运维
|
||||
#bugly
|
||||
-dontwarn com.tencent.bugly.**
|
||||
-keep public class com.tencent.bugly.**{*;}
|
||||
|
||||
# Umeng
|
||||
-keepclassmembers class * {
|
||||
public <init> (org.json.JSONObject);
|
||||
}
|
||||
-keep public class wgyscsf.quickapp.R$*{
|
||||
public static final int *;
|
||||
}
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
## UmengPush
|
||||
-dontwarn com.taobao.**
|
||||
-dontwarn anet.channel.**
|
||||
-dontwarn anetwork.channel.**
|
||||
-dontwarn org.android.**
|
||||
-dontwarn org.apache.thrift.**
|
||||
-dontwarn com.xiaomi.**
|
||||
-dontwarn com.huawei.**
|
||||
-keepattributes *Annotation*
|
||||
-keep class com.taobao.** {*;}
|
||||
-keep class org.android.** {*;}
|
||||
-keep class anet.channel.** {*;}
|
||||
-keep class com.umeng.** {*;}
|
||||
-keep class com.xiaomi.** {*;}
|
||||
-keep class com.huawei.** {*;}
|
||||
-keep class org.apache.thrift.** {*;}
|
||||
-keep class com.alibaba.sdk.android.**{*;}
|
||||
-keep class com.ut.**{*;}
|
||||
-keep class com.ta.**{*;}
|
||||
-keep public class **.R$*{
|
||||
public static final int *;
|
||||
}
|
||||
|
||||
#(可选)避免Log打印输出
|
||||
#-assumenosideeffects class android.util.Log {
|
||||
# public static *** v(...);
|
||||
# public static *** d(...);
|
||||
# public static *** i(...);
|
||||
# public static *** w(...);
|
||||
# }
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# rx
|
||||
-dontwarn javax.annotation.**
|
||||
-dontwarn javax.inject.**
|
||||
# OkHttp3
|
||||
-dontwarn okhttp3.logging.**
|
||||
-keep class okhttp3.internal.**{*;}
|
||||
-dontwarn okio.**
|
||||
# Retrofit
|
||||
-dontwarn retrofit2.**
|
||||
-keep class retrofit2.** {*;}
|
||||
-keepattributes Signature
|
||||
-keepattributes Exceptions
|
||||
|
||||
# RxJava RxAndroid
|
||||
-dontwarn sun.misc.**
|
||||
-keepclassmembers class rx.internal.util.unsafe.*ArrayQueue*Field* {
|
||||
long producerIndex;
|
||||
long consumerIndex;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueProducerNodeRef {
|
||||
rx.internal.util.atomic.LinkedQueueNode producerNode;
|
||||
}
|
||||
-keepclassmembers class rx.internal.util.unsafe.BaseLinkedQueueConsumerNodeRef {
|
||||
rx.internal.util.atomic.LinkedQueueNode consumerNode;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#################################################其它第三方########################
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.tophold.example;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.test.InstrumentationRegistry;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumentation test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() throws Exception {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||
|
||||
assertEquals("com.tophold.example", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.tophold.example">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
|
||||
<application
|
||||
android:name=".MyApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="${app_names}"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme"
|
||||
tools:ignore="GoogleAppIndexingWarning">
|
||||
<activity android:name=".MainActivity">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name=".demo.fund.FundActivity" />
|
||||
<activity android:name=".demo.kview.beginner.ui.KViewVerticalActivity" />
|
||||
<activity
|
||||
android:name=".demo.kview.beginner.ui.KViewHorizontalActivityActivity"
|
||||
android:screenOrientation="landscape"
|
||||
android:theme="@style/AppTheme_Fullscreen" />
|
||||
<activity android:name=".demo.kview.forex.ui.ForexListActivity" />
|
||||
<activity android:name=".demo.kview.forex.ui.ForexActivity" />
|
||||
<activity android:name=".demo.kview.btc.ui.HuobiListActivity" />
|
||||
<activity android:name=".demo.kview.btc.ui.HuobiActivity" />
|
||||
<activity android:name=".demo.pie.PieChartActivity" />
|
||||
|
||||
<!-- <intent-filter> -->
|
||||
<!-- <action android:name="android.intent.action.MAIN"/> -->
|
||||
|
||||
|
||||
<!-- <category android:name="android.intent.category.LAUNCHER"/> -->
|
||||
<!-- </intent-filter> -->
|
||||
<activity android:name=".demo.seekbar.DoubleThumbSeekBarActivity" />
|
||||
<activity android:name=".demo.kview.KViewActivity"></activity>
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -0,0 +1,202 @@
|
||||
[
|
||||
{
|
||||
"actual": "103",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "102",
|
||||
"historyId": 449366,
|
||||
"previous": "103",
|
||||
"revised": "",
|
||||
"timestamp": 1456213500
|
||||
},
|
||||
{
|
||||
"actual": "102",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "103",
|
||||
"historyId": 449367,
|
||||
"previous": "103",
|
||||
"revised": "101",
|
||||
"timestamp": 1458805500
|
||||
},
|
||||
{
|
||||
"actual": "105",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "101",
|
||||
"historyId": 449368,
|
||||
"previous": "102",
|
||||
"revised": "104",
|
||||
"timestamp": 1461221100
|
||||
},
|
||||
{
|
||||
"actual": "104",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "104",
|
||||
"historyId": 449369,
|
||||
"previous": "105",
|
||||
"revised": "",
|
||||
"timestamp": 1464072300
|
||||
},
|
||||
{
|
||||
"actual": "102",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "103",
|
||||
"historyId": 449370,
|
||||
"previous": "104",
|
||||
"revised": "",
|
||||
"timestamp": 1466664300
|
||||
},
|
||||
{
|
||||
"actual": "103",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "101",
|
||||
"historyId": 449371,
|
||||
"previous": "102",
|
||||
"revised": "",
|
||||
"timestamp": 1469083500
|
||||
},
|
||||
{
|
||||
"actual": "101",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "103",
|
||||
"historyId": 449372,
|
||||
"previous": "103",
|
||||
"revised": "",
|
||||
"timestamp": 1472107500
|
||||
},
|
||||
{
|
||||
"actual": "103",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "101",
|
||||
"historyId": 449373,
|
||||
"previous": "101",
|
||||
"revised": "",
|
||||
"timestamp": 1474526700
|
||||
},
|
||||
{
|
||||
"actual": "103",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "103",
|
||||
"historyId": 449374,
|
||||
"previous": "103",
|
||||
"revised": "102",
|
||||
"timestamp": 1477377900
|
||||
},
|
||||
{
|
||||
"actual": "102",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "102",
|
||||
"historyId": 449375,
|
||||
"previous": "103",
|
||||
"revised": "103",
|
||||
"timestamp": 1479973500
|
||||
},
|
||||
{
|
||||
"actual": "106",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "103",
|
||||
"historyId": 449376,
|
||||
"previous": "102",
|
||||
"revised": "",
|
||||
"timestamp": 1481874300
|
||||
},
|
||||
{
|
||||
"actual": "106",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "106",
|
||||
"historyId": 449377,
|
||||
"previous": "106",
|
||||
"revised": "",
|
||||
"timestamp": 1485330300
|
||||
},
|
||||
{
|
||||
"actual": "107",
|
||||
"createTime": "Apr 10, 2017 12:04:14 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "106",
|
||||
"historyId": 449378,
|
||||
"previous": "106",
|
||||
"revised": "",
|
||||
"timestamp": 1487835900
|
||||
},
|
||||
{
|
||||
"actual": "105",
|
||||
"createTime": "Aug 8, 2017 12:35:07 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "107",
|
||||
"historyId": 692633,
|
||||
"previous": "107",
|
||||
"revised": "104",
|
||||
"timestamp": 1490255100
|
||||
},
|
||||
{
|
||||
"actual": "108",
|
||||
"createTime": "Aug 8, 2017 12:35:07 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "104",
|
||||
"historyId": 692634,
|
||||
"previous": "105",
|
||||
"revised": "104",
|
||||
"timestamp": 1493102700
|
||||
},
|
||||
{
|
||||
"actual": "109",
|
||||
"createTime": "Aug 8, 2017 12:35:07 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "108",
|
||||
"historyId": 692635,
|
||||
"previous": "109",
|
||||
"revised": "",
|
||||
"timestamp": 1495521900
|
||||
},
|
||||
{
|
||||
"actual": "109",
|
||||
"createTime": "Aug 8, 2017 12:35:07 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "109",
|
||||
"historyId": 692636,
|
||||
"previous": "109",
|
||||
"revised": "108",
|
||||
"timestamp": 1498113900
|
||||
},
|
||||
{
|
||||
"actual": "109",
|
||||
"createTime": "Aug 8, 2017 12:35:07 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "108",
|
||||
"historyId": 692637,
|
||||
"previous": "109",
|
||||
"revised": "108",
|
||||
"timestamp": 1500965100
|
||||
},
|
||||
{
|
||||
"actual": "111",
|
||||
"createTime": "Aug 24, 2017 6:14:38 PM",
|
||||
"economicId": 518,
|
||||
"forecast": "108",
|
||||
"historyId": 696718,
|
||||
"previous": "108",
|
||||
"revised": "109",
|
||||
"timestamp": 1503557100
|
||||
},
|
||||
{
|
||||
"actual": "110",
|
||||
"createTime": "Oct 9, 2017 9:07:19 AM",
|
||||
"economicId": 518,
|
||||
"forecast": "",
|
||||
"historyId": 698671,
|
||||
"previous": "111",
|
||||
"revised": "",
|
||||
"timestamp": 1506408300
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,100 @@
|
||||
[
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:42:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:43:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:44:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:45:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:46:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:47:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:48:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:42:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:43:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:44:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:45:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:46:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:47:00 AM"
|
||||
},
|
||||
{
|
||||
"c": "149.1755",
|
||||
"h": "149.1935",
|
||||
"l": "149.1755",
|
||||
"o": "149.1755",
|
||||
"t": "Nov 21, 2017 8:48:00 AM"
|
||||
}
|
||||
]
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.tophold.example;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.example.demo.fund.FundActivity;
|
||||
import com.tophold.example.demo.kview.KViewActivity;
|
||||
import com.tophold.example.demo.kview.beginner.ui.KViewHorizontalActivityActivity;
|
||||
import com.tophold.example.demo.kview.beginner.ui.KViewVerticalActivity;
|
||||
import com.tophold.example.demo.kview.btc.ui.HuobiListActivity;
|
||||
import com.tophold.example.demo.kview.forex.ui.ForexListActivity;
|
||||
import com.tophold.example.demo.pie.PieChartActivity;
|
||||
import com.tophold.example.demo.seekbar.DoubleThumbSeekBarActivity;
|
||||
import com.tophold.example.utils.RxUtils;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableEmitter;
|
||||
import io.reactivex.ObservableOnSubscribe;
|
||||
import io.reactivex.Scheduler;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
public class MainActivity extends BaseActivity {
|
||||
TextView mTextView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
mTextView = (TextView) findViewById(R.id.version);
|
||||
mTextView.setText(getVersionStr());
|
||||
}
|
||||
|
||||
public String getVersionStr() {
|
||||
String version = "verisonName:";
|
||||
version += BuildConfig.VERSION_NAME;
|
||||
version += ",versionCode(git head):" + BuildConfig.VERSION_CODE;
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
public void fundView(View view) {
|
||||
go(FundActivity.class);
|
||||
}
|
||||
|
||||
public void kViewDemo(View view) {
|
||||
go(KViewActivity.class);
|
||||
}
|
||||
|
||||
public void onPieTest(View view) {
|
||||
go(PieChartActivity.class);
|
||||
}
|
||||
|
||||
public void onSeekBarTest(View view) {
|
||||
go(DoubleThumbSeekBarActivity.class);
|
||||
}
|
||||
|
||||
|
||||
public void onRx(View view) {
|
||||
Disposable disposable = Observable.create((ObservableOnSubscribe<String>) emitter -> {
|
||||
while (true) {
|
||||
emitter.onNext("a");
|
||||
Thread.sleep(500);
|
||||
emitter.onNext("b");
|
||||
Thread.sleep(2000);
|
||||
emitter.onNext("c");
|
||||
Thread.sleep(9000);
|
||||
emitter.onNext("d");
|
||||
}
|
||||
}).observeOn(Schedulers.io())
|
||||
.compose(RxUtils.rxApiSchedulerHelper())
|
||||
.sample(1000, TimeUnit.MILLISECONDS)
|
||||
.subscribe(s -> Log.d(TAG, "accept: " + s));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.tophold.example;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.tophold.example.demo.kview.btc.api.HuobiWebSocket;
|
||||
import com.tophold.example.demo.kview.forex.api.ForexWebSocket;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:38
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class MyApplication extends Application {
|
||||
public static Context mAppContext;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
mAppContext = this;
|
||||
ForexWebSocket.getInstance().init();
|
||||
HuobiWebSocket.getInstance().init();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
package com.tophold.example.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.annotation.DrawableRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
import com.tophold.example.demo.kview.forex.api.RetrofitManager;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf
|
||||
* 创建日期 :2017/10/16 16:27
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class BaseActivity extends AppCompatActivity {
|
||||
/**
|
||||
* Activity 跳转
|
||||
*
|
||||
* @param clazz 目标activity
|
||||
* @param bundle 传递参数
|
||||
* @param finish 是否结束当前activity
|
||||
*/
|
||||
public static final int NON_CODE = -1;
|
||||
|
||||
protected Context mContext = null;
|
||||
protected String TAG = null;
|
||||
protected Activity mActivity;
|
||||
/**
|
||||
* 对系统系统的toast进行简单封装,方便使用
|
||||
*/
|
||||
private Toast toast = null;
|
||||
|
||||
private CompositeDisposable compositeDisposable;
|
||||
|
||||
@Override
|
||||
public void setContentView(int view) {
|
||||
super.setContentView(view);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
mActivity = this;
|
||||
mContext = this;
|
||||
TAG = this.getClass().getSimpleName();
|
||||
// getBundleExtras
|
||||
Bundle extras = getIntent().getExtras();
|
||||
if (null != extras) {
|
||||
getBundleExtras(extras);
|
||||
}
|
||||
if (isBindEventBusHere()) {
|
||||
EventBus.getDefault().register(mActivity);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBindEventBusHere() {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void getBundleExtras(Bundle extras) {
|
||||
|
||||
}
|
||||
protected Drawable getCompatDrawable(@DrawableRes int drawbaleId) {
|
||||
return ContextCompat.getDrawable(mContext, drawbaleId);
|
||||
}
|
||||
|
||||
protected int getCompatColor(@ColorRes int colorId) {
|
||||
return ContextCompat.getColor(mContext, colorId);
|
||||
}
|
||||
/**
|
||||
* 添加disposable
|
||||
*
|
||||
* @param disposable
|
||||
*/
|
||||
public void unSubscription(Disposable disposable) {
|
||||
if (compositeDisposable == null) {
|
||||
synchronized (CompositeDisposable.class) {
|
||||
if (compositeDisposable == null) {
|
||||
compositeDisposable = new CompositeDisposable();
|
||||
}
|
||||
}
|
||||
}
|
||||
compositeDisposable.add(disposable);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (isBindEventBusHere()) {
|
||||
EventBus.getDefault().unregister(mActivity);
|
||||
}
|
||||
if (compositeDisposable != null) {
|
||||
Log.d(TAG, "base activity dispose");
|
||||
compositeDisposable.clear();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @param observable
|
||||
* @param observer
|
||||
*/
|
||||
public void call(Observable observable, Observer observer) {
|
||||
RetrofitManager.call(observable, observer);
|
||||
}
|
||||
/**
|
||||
* startActivity
|
||||
*
|
||||
* @param clazz target Activity
|
||||
*/
|
||||
public void go(Class<? extends Activity> clazz) {
|
||||
_goActivity(clazz, null, NON_CODE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivity with bundle
|
||||
*
|
||||
* @param clazz target Activity
|
||||
* @param bundle
|
||||
*/
|
||||
public void go(Class<? extends Activity> clazz, Bundle bundle) {
|
||||
_goActivity(clazz, bundle, NON_CODE, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivity then finish this
|
||||
*
|
||||
* @param clazz target Activity
|
||||
*/
|
||||
public void goAndFinish(Class<? extends Activity> clazz) {
|
||||
_goActivity(clazz, null, NON_CODE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivity with bundle and then finish this
|
||||
*
|
||||
* @param clazz target Activity
|
||||
* @param bundle bundle extra
|
||||
*/
|
||||
public void goAndFinish(Class<? extends Activity> clazz, Bundle bundle) {
|
||||
_goActivity(clazz, bundle, NON_CODE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivityForResult
|
||||
*
|
||||
* @param clazz
|
||||
* @param requestCode
|
||||
*/
|
||||
protected void goForResult(Class<? extends Activity> clazz, int requestCode) {
|
||||
_goActivity(clazz, null, requestCode, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivityForResult with bundle
|
||||
*
|
||||
* @param clazz
|
||||
* @param bundle
|
||||
* @param requestCode
|
||||
*/
|
||||
protected void goForResult(Class<? extends Activity> clazz, Bundle bundle, int requestCode) {
|
||||
_goActivity(clazz, bundle, requestCode, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivityForResult then finish this
|
||||
*
|
||||
* @param clazz
|
||||
* @param requestCode
|
||||
*/
|
||||
protected void goForResultAndFinish(Class<? extends Activity> clazz, int requestCode) {
|
||||
_goActivity(clazz, null, requestCode, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* startActivityForResult with bundle and then finish this
|
||||
*
|
||||
* @param clazz
|
||||
* @param bundle
|
||||
* @param requestCode
|
||||
*/
|
||||
protected void goForResultAndFinish(Class<? extends Activity> clazz, Bundle bundle, int requestCode) {
|
||||
_goActivity(clazz, bundle, requestCode, true);
|
||||
}
|
||||
|
||||
|
||||
//可以立刻刷新Toast。推荐使用该方式。
|
||||
public void showSingletonToast(String str) {
|
||||
if (toast == null) {
|
||||
toast = Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT);
|
||||
} else {
|
||||
toast.setText(str);
|
||||
}
|
||||
toast.show();
|
||||
}
|
||||
|
||||
public void showToast(String msg) {
|
||||
showToast(msg, Toast.LENGTH_SHORT);
|
||||
}
|
||||
|
||||
public void showToast(String msg, int toastDuration) {
|
||||
if (null != msg && (toastDuration == Toast.LENGTH_SHORT || toastDuration == Toast.LENGTH_LONG)) {
|
||||
Toast.makeText(getApplicationContext(), msg, toastDuration).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void _goActivity(Class<? extends Activity> clazz, Bundle bundle, int requestCode, boolean finish) {
|
||||
if (null == clazz) {
|
||||
throw new IllegalArgumentException("you must pass a target activity where to go.");
|
||||
}
|
||||
Intent intent = new Intent(this, clazz);
|
||||
if (null != bundle) {
|
||||
intent.putExtras(bundle);
|
||||
}
|
||||
if (requestCode > NON_CODE) {
|
||||
startActivityForResult(intent, requestCode);
|
||||
} else {
|
||||
startActivity(intent);
|
||||
}
|
||||
if (finish) {
|
||||
finish();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.tophold.example.base;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.CompositeDisposable;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import com.tophold.example.demo.kview.forex.api.RetrofitManager;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 14:06
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class BaseFragment extends android.support.v4.app.Fragment {
|
||||
CompositeDisposable disposables;
|
||||
|
||||
protected String TAG;
|
||||
protected Context mContext;
|
||||
protected Activity mActivity;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
TAG = this.getClass().getSimpleName();
|
||||
mContext = this.getActivity();
|
||||
mActivity = getActivity();
|
||||
if (isBindEventBusHere()) {
|
||||
EventBus.getDefault().register(this);
|
||||
}
|
||||
}
|
||||
public boolean isBindEventBusHere() {
|
||||
return false;
|
||||
}
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (isBindEventBusHere()) {
|
||||
EventBus.getDefault().unregister(this);
|
||||
}
|
||||
if (disposables != null) disposables.clear();
|
||||
}
|
||||
|
||||
public void unSubscription(Disposable disposable) {
|
||||
if (disposables == null) {
|
||||
synchronized (CompositeDisposable.class) {
|
||||
if (disposables == null) {
|
||||
disposables = new CompositeDisposable();
|
||||
}
|
||||
}
|
||||
}
|
||||
disposables.add(disposable);
|
||||
}
|
||||
/**
|
||||
* @param observable
|
||||
* @param observer
|
||||
*/
|
||||
public void call(Observable observable, Observer<?> observer) {
|
||||
RetrofitManager.call(observable, observer);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package com.tophold.example.demo.fund;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.beginner.model.OriginFundMode;
|
||||
import com.tophold.example.demo.kview.beginner.api.FundSimulateNetAPI;
|
||||
import com.tophold.example.utils.GsonUtil;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
import com.tophold.trade.view.fund.FundMode;
|
||||
import com.tophold.trade.view.fund.FundView;
|
||||
|
||||
public class FundActivity extends BaseActivity {
|
||||
private FundView mFundView;
|
||||
List<OriginFundMode> mOriginFundModeList;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_fund);
|
||||
initView();
|
||||
initData();
|
||||
loadData();
|
||||
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mFundView = (FundView) findViewById(R.id.af_fv_fundview);
|
||||
|
||||
/**
|
||||
* 定制,所有的画笔以及其它属性都已经暴露出来,有了更加大的定时灵活性。更多参数可以直接查看源码...
|
||||
*/
|
||||
//常规set、get...
|
||||
mFundView.getBrokenPaint().setColor(getResources().getColor(R.color.colorAccent));//设置折现颜色
|
||||
mFundView.getInnerXPaint().setStrokeWidth(1);//设置内部x轴虚线的宽度,px
|
||||
mFundView.getBrokenPaint().setStrokeWidth(1);
|
||||
//链式调用
|
||||
mFundView
|
||||
.setBasePaddingTop(140)
|
||||
.setBasePaddingLeft(50)
|
||||
.setBasePaddingRight(40)
|
||||
.setBasePaddingBottom(30)
|
||||
.setLoadingText("正在加载,马上就来...");
|
||||
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mOriginFundModeList = new ArrayList<>();
|
||||
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
Disposable subscribe = Observable.timer(StringUtils.getRadomNum(500, 3000), TimeUnit.MILLISECONDS)
|
||||
.map(map -> {
|
||||
String originalFundData = FundSimulateNetAPI.getOriginalFundData(mContext);
|
||||
if (originalFundData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return null;
|
||||
}
|
||||
OriginFundMode[] originFunModes;
|
||||
try {
|
||||
originFunModes = GsonUtil.fromJson2Object(originalFundData, OriginFundMode[].class);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
List<OriginFundMode> OriginFundModeList = Arrays.asList(originFunModes);
|
||||
//开始适配图表数据
|
||||
return adapterData(OriginFundModeList);
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
mData -> {
|
||||
if (StringUtils.isEmpty(mData)) {
|
||||
Log.d(TAG, "loadData: data is empty!");
|
||||
return;
|
||||
}
|
||||
mFundView.setDataList(mData);
|
||||
}
|
||||
, throwable -> throwable.printStackTrace());
|
||||
|
||||
unSubscription(subscribe);
|
||||
}
|
||||
|
||||
private List<FundMode> adapterData(List<OriginFundMode> originFundModeList) {
|
||||
List<FundMode> fundModeList = new ArrayList<>();//适配后的数据
|
||||
for (OriginFundMode originFundMode : originFundModeList) {
|
||||
FundMode fundMode = new FundMode(originFundMode.timestamp * 1000, originFundMode.actual);
|
||||
fundModeList.add(fundMode);
|
||||
Log.e(TAG, "adapterData: 适配之前:" + originFundMode.actual + "----->>" + fundMode.dataY);
|
||||
}
|
||||
return fundModeList;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.tophold.example.demo.kview
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import com.tophold.example.BuildConfig
|
||||
import com.tophold.example.R
|
||||
import com.tophold.example.base.BaseActivity
|
||||
import com.tophold.example.demo.kview.beginner.ui.KViewHorizontalActivityActivity
|
||||
import com.tophold.example.demo.kview.beginner.ui.KViewVerticalActivity
|
||||
import com.tophold.example.demo.kview.btc.ui.HuobiListActivity
|
||||
import com.tophold.example.demo.kview.forex.ui.ForexListActivity
|
||||
|
||||
class KViewActivity : BaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_kview)
|
||||
}
|
||||
|
||||
fun kViewVertical(view: View) {
|
||||
go(KViewVerticalActivity::class.java)
|
||||
}
|
||||
|
||||
fun kViewHorizontal(view: View) {
|
||||
go(KViewHorizontalActivityActivity::class.java)
|
||||
}
|
||||
|
||||
fun kViewEvaluation(view: View) {
|
||||
go(ForexListActivity::class.java)
|
||||
}
|
||||
|
||||
fun btnDemo(view: View) {
|
||||
go(HuobiListActivity::class.java)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.tophold.example.demo.kview.beginner.api;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2017/10/25 15:43
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class FundSimulateNetAPI {
|
||||
/**
|
||||
* 获取去最原始的数据信息
|
||||
*
|
||||
* @return json data
|
||||
*/
|
||||
public static String getOriginalFundData(Context context) {
|
||||
InputStream input = null;
|
||||
try {
|
||||
input = context.getAssets().open("fund.json");
|
||||
String json = convertStreamToString(input);
|
||||
return json;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* input 流转换为字符串
|
||||
*
|
||||
* @param is
|
||||
* @return
|
||||
*/
|
||||
private static String convertStreamToString(java.io.InputStream is) {
|
||||
String s = null;
|
||||
try {
|
||||
Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A");
|
||||
if (scanner.hasNext()) s = scanner.next();
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package com.tophold.example.demo.kview.beginner.api;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Scanner;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2017/10/25 15:43
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class KViewSimulateNetAPI {
|
||||
/**
|
||||
* 获取去最原始的数据信息
|
||||
*
|
||||
* @return json data
|
||||
*/
|
||||
public static String getOriginalFundData(Context context, int index) {
|
||||
InputStream input = null;
|
||||
try {
|
||||
input = context.getAssets().open("timesharing" + index + ".json");
|
||||
String json = convertStreamToString(input);
|
||||
return json;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* input 流转换为字符串
|
||||
*
|
||||
* @param is
|
||||
* @return
|
||||
*/
|
||||
private static String convertStreamToString(InputStream is) {
|
||||
String s = null;
|
||||
try {
|
||||
Scanner scanner = new Scanner(is, "UTF-8").useDelimiter("\\A");
|
||||
if (scanner.hasNext()) s = scanner.next();
|
||||
is.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.tophold.example.demo.kview.beginner.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2017/10/24 15:00
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class OriginFundMode implements Serializable {
|
||||
/**
|
||||
* actual : 103
|
||||
* createTime : Apr 10, 2017 12:04:14 AM
|
||||
* economicId : 518
|
||||
* forecast : 102
|
||||
* historyId : 449366
|
||||
* previous : 103
|
||||
* revised :
|
||||
* timestamp : 1456213500
|
||||
*/
|
||||
|
||||
public String actual;
|
||||
public String createTime;
|
||||
public int economicId;
|
||||
public String forecast;
|
||||
public int historyId;
|
||||
public String previous;
|
||||
public String revised;
|
||||
public long timestamp;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.tophold.example.demo.kview.beginner.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2017/11/21 11:09
|
||||
* 描 述 :原始数据
|
||||
* ============================================================
|
||||
**/
|
||||
public class OriginQuotes implements Serializable {
|
||||
/**
|
||||
* t : 2016-10-25 12:06:00
|
||||
* o : 2357.25
|
||||
* h : 2357.25
|
||||
* l : 2357.25
|
||||
* c : 2357.25
|
||||
*/
|
||||
public String t;
|
||||
public String o;
|
||||
public String h;
|
||||
public String l;
|
||||
public String c;
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
package com.tophold.example.demo.kview.beginner.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.beginner.model.OriginQuotes;
|
||||
import com.tophold.example.demo.kview.beginner.api.KViewSimulateNetAPI;
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.trade.utils.FormatUtil;
|
||||
import com.tophold.example.utils.GsonUtil;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
import com.tophold.trade.utils.TimeUtils;
|
||||
import com.tophold.trade.view.kview.KView;
|
||||
import com.tophold.trade.view.kview.KViewListener;
|
||||
import com.tophold.trade.view.kview.Quotes;
|
||||
|
||||
/**
|
||||
* timesharing0:模拟的是加载更多的数据,注意,会分段取,模拟的是多次加载更多
|
||||
* timesharing1:模拟的是api请求的数据集合,注意:一次加载完毕,模拟的是第一次加载的数据
|
||||
* timesharing2:模拟的是实时**推送**的数据,注意:会分段取,一次取一个。
|
||||
*/
|
||||
public class KViewHorizontalActivityActivity extends BaseActivity {
|
||||
//bind view
|
||||
private LinearLayout mAkvLlContainer;
|
||||
private TextView mAkvTvH;
|
||||
private TextView mAkvTvO;
|
||||
private TextView mAkvTvTime;
|
||||
private TextView mAkvTvL;
|
||||
private TextView mAkvTvC;
|
||||
private TextView mAkvTvP;
|
||||
private KView mAkvKvKview;
|
||||
|
||||
//模拟网络过来的列表数据
|
||||
List<Quotes> mQuotesList;
|
||||
//模拟加载更多的数据
|
||||
List<Quotes> mLoadMoreData;
|
||||
//模拟socket推送过来的单个数据
|
||||
List<Quotes> mPushData;
|
||||
//加载更多,加载到哪儿了。因为真实应用中,也存在加载完毕的情况。这里对应加载到list的最后
|
||||
int index = 0;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_kview_horizontal);
|
||||
initView();
|
||||
initData();
|
||||
loadData();
|
||||
pushData();
|
||||
}
|
||||
|
||||
private void pushData() {
|
||||
Disposable disposable = Observable.interval(StringUtils.getRadomNum(300, 3000), TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> {
|
||||
int size = mPushData.size();
|
||||
if (data < size) {
|
||||
mAkvKvKview.pushKViewData(mPushData.get(data.intValue()), 0);
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
, throwable -> throwable.printStackTrace());
|
||||
|
||||
unSubscription(disposable);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);
|
||||
mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);
|
||||
mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);
|
||||
mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);
|
||||
mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);
|
||||
mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);
|
||||
mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);
|
||||
mAkvKvKview = (KView) findViewById(R.id.akv_kv_kview);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mQuotesList = new ArrayList<>();
|
||||
mLoadMoreData = new ArrayList<>();
|
||||
mPushData = new ArrayList<>();
|
||||
|
||||
//这里先预加载加载更多的数据,然后加载更多的时候分段取出来,模拟加载更多
|
||||
initLoadMoreData();
|
||||
|
||||
//pushData
|
||||
initPushData();
|
||||
|
||||
}
|
||||
|
||||
private void initPushData() {
|
||||
String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 2);
|
||||
if (originalFundData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return;
|
||||
}
|
||||
List<OriginQuotes> OriginFundModeList;
|
||||
try {
|
||||
OriginFundModeList = GsonUtil.fromJson2Object(originalFundData, new TypeToken<List<OriginQuotes>>() {
|
||||
}.getType());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
//开始适配图表数据
|
||||
mPushData = adapterData(OriginFundModeList);
|
||||
|
||||
}
|
||||
|
||||
private void initLoadMoreData() {
|
||||
String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 0);
|
||||
if (originalFundData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<OriginQuotes> quotesList = GsonUtil.fromJson2Object(originalFundData,
|
||||
new TypeToken<List<OriginQuotes>>() {
|
||||
}.getType());
|
||||
mLoadMoreData = adapterData(quotesList);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
//模拟网络环境加载数据列表
|
||||
Disposable disposable = Observable.timer(StringUtils.getRadomNum(500, 2000),
|
||||
TimeUnit.MILLISECONDS)
|
||||
.doOnNext(data -> {
|
||||
String originalData = KViewSimulateNetAPI.getOriginalFundData(mContext, 2);
|
||||
if (originalData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<OriginQuotes> originQuotes = GsonUtil
|
||||
.fromJson2Object(originalData, new TypeToken<List<OriginQuotes>>() {
|
||||
}.getType());
|
||||
mQuotesList = adapterData(originQuotes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "loadData: json转换错误");
|
||||
return;
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> mAkvKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {
|
||||
@Override
|
||||
public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {
|
||||
showContanier(preQuotes, currentQuotes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnLongTouch() {
|
||||
mAkvLlContainer.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void needLoadMore() {
|
||||
loadMore();
|
||||
}
|
||||
}),
|
||||
Throwable::printStackTrace
|
||||
);
|
||||
unSubscription(disposable);
|
||||
}
|
||||
|
||||
private void loadMore() {
|
||||
if (mLoadMoreData == null) return;
|
||||
Disposable disposable = Observable.timer(StringUtils.getRadomNum(1000, 5000), TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> {
|
||||
int size = mLoadMoreData.size();
|
||||
int min = size / 20;
|
||||
int max = size / 5;//一次最多加载多少
|
||||
int loadSize = StringUtils.getRadomNum(min, max);
|
||||
if (index == loadSize) {
|
||||
//没有更多数据了
|
||||
mAkvKvKview.loadMoreNoData();
|
||||
}
|
||||
if ((index + loadSize) > mLoadMoreData.size()) {
|
||||
loadSize = mLoadMoreData.size();
|
||||
}
|
||||
List<Quotes> loadList = mLoadMoreData.subList(index, index + loadSize);
|
||||
index = index + loadSize;//重置起始位置
|
||||
mAkvKvKview.loadKViewData(loadList);
|
||||
}
|
||||
, throwable -> throwable.printStackTrace());
|
||||
unSubscription(disposable);
|
||||
|
||||
}
|
||||
|
||||
private List<Quotes> adapterData(List<OriginQuotes> originFundModeList) {
|
||||
List<Quotes> fundModeList = new ArrayList<>();//适配后的数据
|
||||
for (OriginQuotes OriginQuotes : originFundModeList) {
|
||||
Quotes Quotes = new Quotes(OriginQuotes.o, OriginQuotes.h, OriginQuotes.l,
|
||||
OriginQuotes.c, OriginQuotes.t);
|
||||
fundModeList.add(Quotes);
|
||||
}
|
||||
return fundModeList;
|
||||
}
|
||||
|
||||
private void showContanier(Quotes preQuotes, Quotes currentQuotes) {
|
||||
mAkvLlContainer.setVisibility(View.VISIBLE);
|
||||
int digits = 4;
|
||||
boolean isPositive;
|
||||
String precent;
|
||||
double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;
|
||||
isPositive = dis >= 0;
|
||||
precent = FormatUtil.formatBySubString(dis, 2);
|
||||
precent += "%";
|
||||
|
||||
//
|
||||
mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));
|
||||
mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));
|
||||
mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));
|
||||
mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));
|
||||
mAkvTvP.setText(precent);
|
||||
mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat("MM-dd HH:mm")));
|
||||
|
||||
if (isPositive) {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
} else {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMyColor(@ColorRes int colorId) {
|
||||
return getResources().getColor(colorId);
|
||||
}
|
||||
|
||||
public void showCandle(View view) {
|
||||
boolean showTimSharing = mAkvKvKview.isShowTimSharing();
|
||||
mAkvKvKview.setShowTimSharing(!showTimSharing);
|
||||
if (!showTimSharing) {
|
||||
((Button) view).setText("点击展示蜡烛图");
|
||||
} else {
|
||||
((Button) view).setText("点击展示分时图");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
package com.tophold.example.demo.kview.beginner.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.beginner.api.KViewSimulateNetAPI;
|
||||
import com.tophold.example.demo.kview.beginner.model.OriginQuotes;
|
||||
import com.tophold.trade.utils.FormatUtil;
|
||||
import com.tophold.example.utils.GsonUtil;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
import com.tophold.trade.utils.TimeUtils;
|
||||
import com.tophold.trade.view.kview.KView;
|
||||
import com.tophold.trade.view.kview.KViewListener;
|
||||
import com.tophold.trade.view.kview.Quotes;
|
||||
|
||||
/**
|
||||
* timesharing0:模拟的是加载更多的数据,注意,会分段取,模拟的是多次加载更多
|
||||
* timesharing1:模拟的是api请求的数据集合,注意:一次加载完毕,模拟的是第一次加载的数据
|
||||
* timesharing2:模拟的是实时**推送**的数据,注意:会分段取,一次取一个。
|
||||
*/
|
||||
public class KViewVerticalActivity extends BaseActivity {
|
||||
//bind view
|
||||
private LinearLayout mAkvLlContainer;
|
||||
private TextView mAkvTvH;
|
||||
private TextView mAkvTvO;
|
||||
private TextView mAkvTvTime;
|
||||
private TextView mAkvTvL;
|
||||
private TextView mAkvTvC;
|
||||
private TextView mAkvTvP;
|
||||
private KView mAkvKvKview;
|
||||
private Button mAkvBtnShowCandle;
|
||||
private Button mAkvBtnShowMinnor;
|
||||
|
||||
//模拟网络过来的列表数据
|
||||
List<Quotes> mQuotesList;
|
||||
//模拟加载更多的数据
|
||||
List<Quotes> mLoadMoreData;
|
||||
//模拟socket推送过来的单个数据
|
||||
List<Quotes> mPushData;
|
||||
//加载更多,加载到哪儿了。因为真实应用中,也存在加载完毕的情况。这里对应加载到list的最后
|
||||
int index = 0;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_kview_vertical);
|
||||
initView();
|
||||
initData();
|
||||
loadData();
|
||||
pushData();
|
||||
}
|
||||
|
||||
private void pushData() {
|
||||
Disposable disposable = Observable.interval(StringUtils.getRadomNum(300, 3000), TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> {
|
||||
int size = mPushData.size();
|
||||
if (data < size) {
|
||||
mAkvKvKview.pushKViewData(mPushData.get(data.intValue()), 0);
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
, throwable -> throwable.printStackTrace());
|
||||
|
||||
unSubscription(disposable);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);
|
||||
mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);
|
||||
mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);
|
||||
mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);
|
||||
mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);
|
||||
mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);
|
||||
mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);
|
||||
mAkvKvKview = (KView) findViewById(R.id.akv_kv_kview);
|
||||
mAkvBtnShowCandle = (Button) findViewById(R.id.akv_btn_showCandle);
|
||||
mAkvBtnShowMinnor = (Button) findViewById(R.id.akv_btn_showMinnor);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mQuotesList = new ArrayList<>();
|
||||
mLoadMoreData = new ArrayList<>();
|
||||
mPushData = new ArrayList<>();
|
||||
|
||||
//这里先预加载加载更多的数据,然后加载更多的时候分段取出来,模拟加载更多
|
||||
initLoadMoreData();
|
||||
|
||||
//pushData
|
||||
initPushData();
|
||||
|
||||
}
|
||||
|
||||
private void initPushData() {
|
||||
String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 3);
|
||||
if (originalFundData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return;
|
||||
}
|
||||
List<OriginQuotes> OriginFundModeList;
|
||||
try {
|
||||
OriginFundModeList = GsonUtil.fromJson2Object(originalFundData, new TypeToken<List<OriginQuotes>>() {
|
||||
}.getType());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
//开始适配图表数据
|
||||
mPushData = adapterData(OriginFundModeList);
|
||||
|
||||
}
|
||||
|
||||
private void initLoadMoreData() {
|
||||
String originalFundData = KViewSimulateNetAPI.getOriginalFundData(mContext, 3);
|
||||
if (originalFundData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<OriginQuotes> quotesList = GsonUtil.fromJson2Object(originalFundData,
|
||||
new TypeToken<List<OriginQuotes>>() {
|
||||
}.getType());
|
||||
mLoadMoreData = adapterData(quotesList);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
//模拟网络环境加载数据列表
|
||||
Disposable disposable = Observable.timer(StringUtils.getRadomNum(500, 2000),
|
||||
TimeUnit.MILLISECONDS)
|
||||
.doOnNext(data -> {
|
||||
String originalData = KViewSimulateNetAPI.getOriginalFundData(mContext, 3);
|
||||
if (originalData == null) {
|
||||
Log.e(TAG, "loadData: 从网络获取到的数据为空");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
List<OriginQuotes> originQuotes = GsonUtil
|
||||
.fromJson2Object(originalData, new TypeToken<List<OriginQuotes>>() {
|
||||
}.getType());
|
||||
mQuotesList = adapterData(originQuotes);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Log.e(TAG, "loadData: json转换错误");
|
||||
return;
|
||||
}
|
||||
})
|
||||
.subscribeOn(Schedulers.computation())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> {
|
||||
mAkvKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {
|
||||
@Override
|
||||
public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {
|
||||
showContanier(preQuotes, currentQuotes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnLongTouch() {
|
||||
mAkvLlContainer.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void needLoadMore() {
|
||||
loadMore();
|
||||
}
|
||||
});
|
||||
},
|
||||
throwable -> throwable.printStackTrace()
|
||||
);
|
||||
unSubscription(disposable);
|
||||
}
|
||||
|
||||
private void loadMore() {
|
||||
if (mLoadMoreData == null) return;
|
||||
Disposable disposable = Observable.timer(StringUtils.getRadomNum(1000, 5000), TimeUnit.MILLISECONDS)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(
|
||||
data -> {
|
||||
int size = mLoadMoreData.size();
|
||||
int min = size / 20;
|
||||
int max = size / 5;//一次最多加载多少
|
||||
int loadSize = StringUtils.getRadomNum(min, max);
|
||||
if (index == loadSize) {
|
||||
//没有更多数据了
|
||||
mAkvKvKview.loadMoreNoData();
|
||||
}
|
||||
if ((index + loadSize) > mLoadMoreData.size()) {
|
||||
loadSize = mLoadMoreData.size();
|
||||
}
|
||||
List<Quotes> loadList = mLoadMoreData.subList(index, index + loadSize);
|
||||
index = index + loadSize;//重置起始位置
|
||||
mAkvKvKview.loadKViewData(loadList);
|
||||
}
|
||||
, throwable -> throwable.printStackTrace());
|
||||
unSubscription(disposable);
|
||||
|
||||
}
|
||||
|
||||
public void showCandle(View view) {
|
||||
boolean showTimSharing = mAkvKvKview.isShowTimSharing();
|
||||
mAkvKvKview.setShowTimSharing(!showTimSharing);
|
||||
if (!showTimSharing) {
|
||||
mAkvBtnShowCandle.setText("点击展示蜡烛图");
|
||||
} else {
|
||||
mAkvBtnShowCandle.setText("点击展示分时图");
|
||||
}
|
||||
}
|
||||
|
||||
public void showMinor(View view) {
|
||||
boolean showMinor = mAkvKvKview.isShowMinor();
|
||||
mAkvKvKview.setShowMinor(!showMinor);
|
||||
if (!showMinor) {
|
||||
mAkvBtnShowMinnor.setText("点击不显示副图");
|
||||
} else {
|
||||
mAkvBtnShowMinnor.setText("点击显示副图");
|
||||
}
|
||||
}
|
||||
|
||||
private List<Quotes> adapterData(List<OriginQuotes> originFundModeList) {
|
||||
List<Quotes> fundModeList = new ArrayList<>();//适配后的数据
|
||||
for (OriginQuotes OriginQuotes : originFundModeList) {
|
||||
Quotes Quotes = new Quotes(OriginQuotes.o, OriginQuotes.h, OriginQuotes.l,
|
||||
OriginQuotes.c, OriginQuotes.t);
|
||||
fundModeList.add(Quotes);
|
||||
}
|
||||
return fundModeList;
|
||||
}
|
||||
|
||||
private void showContanier(Quotes preQuotes, Quotes currentQuotes) {
|
||||
mAkvLlContainer.setVisibility(View.VISIBLE);
|
||||
int digits = 4;
|
||||
boolean isPositive;
|
||||
String precent;
|
||||
double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;
|
||||
isPositive = dis >= 0;
|
||||
precent = FormatUtil.formatBySubString(dis, 2);
|
||||
precent += "%";
|
||||
|
||||
//
|
||||
mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));
|
||||
mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));
|
||||
mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));
|
||||
mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));
|
||||
mAkvTvP.setText(precent);
|
||||
mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat("MM-dd HH:mm")));
|
||||
|
||||
if (isPositive) {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
} else {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMyColor(@ColorRes int colorId) {
|
||||
return getResources().getColor(colorId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/28 14:14
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class GZipUtil {
|
||||
// 压缩
|
||||
public static byte[] compress(byte[] data) throws IOException {
|
||||
if (data == null || data.length == 0) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
GZIPOutputStream gzip = new GZIPOutputStream(out);
|
||||
gzip.write(data);
|
||||
gzip.close();
|
||||
return out.toByteArray();//out.toString("ISO-8859-1");
|
||||
}
|
||||
|
||||
public static byte[] compress(String str) throws IOException {
|
||||
if (str == null || str.length() == 0) {
|
||||
return null;
|
||||
}
|
||||
return compress(str.getBytes("utf-8"));
|
||||
}
|
||||
|
||||
// 解压缩
|
||||
public static byte[] uncompress(byte[] data) throws IOException {
|
||||
if (data == null || data.length == 0) {
|
||||
return data;
|
||||
}
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(data);
|
||||
GZIPInputStream gunzip = new GZIPInputStream(in);
|
||||
byte[] buffer = new byte[256];
|
||||
int n;
|
||||
while ((n = gunzip.read(buffer)) >= 0) {
|
||||
out.write(buffer, 0, n);
|
||||
}
|
||||
gunzip.close();
|
||||
in.close();
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
public static String uncompressBytes(byte[] data) throws IOException {
|
||||
byte[] bytes = uncompress(data);
|
||||
return new String(bytes);
|
||||
}
|
||||
|
||||
public static String uncompress(String str) throws IOException {
|
||||
if (str == null || str.length() == 0) {
|
||||
return str;
|
||||
}
|
||||
byte[] data = uncompress(str.getBytes("utf-8")); // ISO-8859-1
|
||||
return new String(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param @param unZipfile
|
||||
* @param @param destFile 指定读取文件,需要从压缩文件中读取文件内容的文件名
|
||||
* @param @return 设定文件
|
||||
* @return String 返回类型
|
||||
* @throws
|
||||
* @Title: unZip
|
||||
* @Description: TODO(这里用一句话描述这个方法的作用)
|
||||
*/
|
||||
public static String unZip(String unZipfile, String destFile) {// unZipfileName需要解压的zip文件名
|
||||
InputStream inputStream;
|
||||
String inData = null;
|
||||
try {
|
||||
// 生成一个zip的文件
|
||||
File f = new File(unZipfile);
|
||||
ZipFile zipFile = new ZipFile(f);
|
||||
|
||||
// 遍历zipFile中所有的实体,并把他们解压出来
|
||||
ZipEntry entry = zipFile.getEntry(destFile);
|
||||
if (!entry.isDirectory()) {
|
||||
// 获取出该压缩实体的输入流
|
||||
inputStream = zipFile.getInputStream(entry);
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
byte[] bys = new byte[4096];
|
||||
for (int p = -1; (p = inputStream.read(bys)) != -1; ) {
|
||||
out.write(bys, 0, p);
|
||||
}
|
||||
inData = out.toString();
|
||||
out.close();
|
||||
inputStream.close();
|
||||
}
|
||||
zipFile.close();
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
return inData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* 拦截器
|
||||
*
|
||||
* 向请求头里添加公共参数
|
||||
* Created by zhouwei on 16/11/10.
|
||||
*/
|
||||
|
||||
public class HttpCommonInterceptor implements Interceptor {
|
||||
|
||||
private Map<String,String> mHeaderParamsMap = new HashMap<>();
|
||||
public HttpCommonInterceptor() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Log.d("HttpCommonInterceptor","add common params");
|
||||
Request oldRequest = chain.request();
|
||||
|
||||
// 添加新的参数,添加到url 中
|
||||
/* HttpUrl.Builder authorizedUrlBuilder = oldRequest.url()
|
||||
.newBuilder()
|
||||
.scheme(oldRequest.url().scheme())
|
||||
.host(oldRequest.url().host());*/
|
||||
|
||||
// 新的请求
|
||||
|
||||
Request.Builder requestBuilder = oldRequest.newBuilder();
|
||||
requestBuilder.method(oldRequest.method(), oldRequest.body());
|
||||
//添加公共参数,添加到header中
|
||||
if(mHeaderParamsMap.size() > 0){
|
||||
for(Map.Entry<String,String> params:mHeaderParamsMap.entrySet()){
|
||||
requestBuilder.header(params.getKey(),params.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
Request newRequest = requestBuilder.build();
|
||||
|
||||
return chain.proceed(newRequest);
|
||||
}
|
||||
|
||||
public static class Builder{
|
||||
HttpCommonInterceptor mHttpCommonInterceptor;
|
||||
|
||||
public Builder(){
|
||||
mHttpCommonInterceptor = new HttpCommonInterceptor();
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, String value){
|
||||
mHttpCommonInterceptor.mHeaderParamsMap.put(key,value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, int value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, float value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, long value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, double value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
|
||||
public HttpCommonInterceptor build(){
|
||||
return mHttpCommonInterceptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.QueryMap;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiData;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiSymbol;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiQuote;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 11:31
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public interface HuobiService {
|
||||
@GET("/market/history/kline")
|
||||
Observable<HuobiData<List<HuobiQuote>>> chartQuotes(@QueryMap Map<String, Object> params);
|
||||
|
||||
@GET("/v1/common/symbols")
|
||||
Observable<HuobiData<List<HuobiSymbol>>> getSymbolList(@QueryMap Map<String, Object> params);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:31
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiSocketApi {
|
||||
public static final String TAG = HuobiSocketApi.class.getSimpleName();
|
||||
|
||||
public static void ping(long time) {
|
||||
String str = "{\"ping\":" + time + "}";
|
||||
sendService(str);
|
||||
}
|
||||
|
||||
public static void pong(long time) {
|
||||
String str = "{\"pong\":" + time + "}";
|
||||
sendService(str);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订阅KLine和取消KLine
|
||||
*
|
||||
* @param id 一个唯一值,建议用时间戳
|
||||
* @param symbol
|
||||
* @param period 周期,不管任何周期,全部转化为时间戳格式
|
||||
* @param sub true:订阅;false:取消订阅
|
||||
*/
|
||||
public static void kLine(long id, String symbol, long period, boolean sub) {
|
||||
String periodByMs = getPeriodByMs(period);
|
||||
if (periodByMs == null) {
|
||||
Log.e(TAG, "subKLine: period 不合法!!!");
|
||||
return;
|
||||
}
|
||||
String kline = "market." + symbol + ".kline." + periodByMs;
|
||||
String json = "{" + (sub ? "\"sub\"" : "\"unsub\"") + ":\"" + kline + "\",\"id\":\"" + id + "\"}";
|
||||
|
||||
sendService(json);
|
||||
|
||||
}
|
||||
|
||||
public static void subKLine(String symbol, long period, boolean sub) {
|
||||
long id = System.currentTimeMillis();
|
||||
kLine(id, symbol, period, sub);
|
||||
}
|
||||
|
||||
private static void sendService(String str) {
|
||||
Log.d(TAG, "sendService: " + str);
|
||||
HuobiWebSocket.getInstance().getWebSocket().send(str);
|
||||
}
|
||||
|
||||
private static String getPeriodByMs(long ms) {
|
||||
long s = ms / 1000;
|
||||
if (s == 1 * 60) return "1min";
|
||||
if (s == 5 * 60) return "5min";
|
||||
if (s == 15 * 60) return "15min";
|
||||
if (s == 30 * 60) return "30min";
|
||||
if (s == 60 * 60) return "60min";
|
||||
if (s == 24 * 60 * 60) return "1day";
|
||||
if (s == 7 * 24 * 60 * 60) return "1week";
|
||||
if (s == 30 * 24 * 60 * 60) return "1mon";
|
||||
if (s == 365 * 24 * 60 * 60) return "1year";
|
||||
Log.d(TAG, "getPeriodByMs: unkonwn ms!!!");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiWsQuote;
|
||||
import com.tophold.example.utils.GsonUtil;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:26
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiSocketParser {
|
||||
public static final String TAG = HuobiSocketParser.class.getSimpleName();
|
||||
|
||||
public static void fix2Object(String str) {
|
||||
Log.d(TAG, "fix2Object: " + str);
|
||||
try {
|
||||
formatJson(str);
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void formatJson(String str) throws JSONException {
|
||||
JSONObject json = new JSONObject(str);
|
||||
if (json.has("ping")) {
|
||||
long ping = json.getLong("ping");
|
||||
HuobiSocketApi.pong(ping);
|
||||
return;
|
||||
}
|
||||
|
||||
//判断不严谨
|
||||
if (json.has("ch")) {
|
||||
HuobiWsQuote huobiWsQuote = GsonUtil.fromJson2Object(str, HuobiWsQuote.class);
|
||||
if (huobiWsQuote != null) {
|
||||
obj2EventBus(huobiWsQuote);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void obj2EventBus(Object object) {
|
||||
EventBus.getDefault().post(object);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import okio.ByteString;
|
||||
import com.tophold.example.BuildConfig;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:15
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiWebSocket {
|
||||
public static final String TAG = HuobiWebSocket.class.getSimpleName();
|
||||
private static final int DEFAULT_TIME_OUT = 20;//超时时间 5s
|
||||
private static final int DEFAULT_READ_TIME_OUT = 20;
|
||||
//temp quotes
|
||||
private static final String BASE_URL = "https://api.huobi.br.com:443/ws";
|
||||
|
||||
Request mRequest;
|
||||
private okhttp3.WebSocket mWebSocket;
|
||||
OkHttpClient client;
|
||||
boolean isConnctted = false;
|
||||
|
||||
public WebSocket getWebSocket() {
|
||||
return mWebSocket;
|
||||
}
|
||||
|
||||
private HuobiWebSocket() {
|
||||
// 创建 OKHttpClient
|
||||
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
|
||||
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
|
||||
builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间
|
||||
builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间
|
||||
builder.pingInterval(5000, TimeUnit.MILLISECONDS);
|
||||
builder.retryOnConnectionFailure(true);//失败重试
|
||||
|
||||
//DEBUG模式下 添加日志拦截器
|
||||
if (BuildConfig.DEBUG) {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
builder.addInterceptor(interceptor);
|
||||
}
|
||||
|
||||
// 添加公共参数拦截器
|
||||
HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
|
||||
.addHeaderParams("paltform", "android")
|
||||
.addHeaderParams("userToken", "1234343434dfdfd3434")
|
||||
.addHeaderParams("userId", "123445")
|
||||
.build();
|
||||
//builder.addInterceptor(commonInterceptor);
|
||||
|
||||
|
||||
//HuobiWebSocket
|
||||
client = builder.build();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
mRequest = new Request.Builder().url(BASE_URL).build();
|
||||
mWebSocket = client.newWebSocket(mRequest, new WebSocketListener() {
|
||||
@Override
|
||||
public void onOpen(okhttp3.WebSocket webSocket, Response response) {
|
||||
super.onOpen(webSocket, response);
|
||||
isConnctted = true;
|
||||
Log.d(TAG, "onOpen: ");
|
||||
//Toast.makeText(MyApplication.mAppContext, "websocket连接成功...", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(okhttp3.WebSocket webSocket, String text) {
|
||||
super.onMessage(webSocket, text);
|
||||
Log.d(TAG, "onMessage: " + text);
|
||||
HuobiSocketParser.fix2Object(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(WebSocket webSocket, ByteString bytes) {
|
||||
super.onMessage(webSocket, bytes);
|
||||
String s = null;
|
||||
try {
|
||||
s = GZipUtil.uncompressBytes(bytes.toByteArray());
|
||||
HuobiSocketParser.fix2Object(s);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) {
|
||||
super.onClosed(webSocket, code, reason);
|
||||
isConnctted = false;
|
||||
Log.d(TAG, "onClosed,code: " + code + ",reason:" + reason);
|
||||
//Toast.makeText(MyApplication.mAppContext, "websocket关闭...", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(okhttp3.WebSocket webSocket, Throwable t, @Nullable Response response) {
|
||||
super.onFailure(webSocket, t, response);
|
||||
isConnctted = false;
|
||||
Log.e(TAG, "onFailure: " + (response != null ? response.toString() : "response==null"));
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final HuobiWebSocket INSTANCE = new HuobiWebSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RetrofitServiceManager
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static HuobiWebSocket getInstance() {
|
||||
return HuobiWebSocket.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.tophold.example.demo.kview.btc.api;
|
||||
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import com.tophold.example.BuildConfig;
|
||||
|
||||
|
||||
public class RetrofitManager {
|
||||
private static final int DEFAULT_TIME_OUT = 20;//超时时间 5s
|
||||
private static final int DEFAULT_READ_TIME_OUT = 20;
|
||||
//temp quotes
|
||||
// private static final String BASE_URL = "https://api.huobipro.com";
|
||||
private static final String BASE_URL = "https://api.huobi.br.com";
|
||||
private Retrofit mRetrofit;
|
||||
|
||||
private RetrofitManager() {
|
||||
// 创建 OKHttpClient
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
|
||||
builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间
|
||||
builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间
|
||||
builder.retryOnConnectionFailure(true);//失败重试
|
||||
|
||||
//DEBUG模式下 添加日志拦截器
|
||||
if (BuildConfig.DEBUG) {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
builder.addInterceptor(interceptor);
|
||||
}
|
||||
|
||||
// 添加公共参数拦截器
|
||||
HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
|
||||
.addHeaderParams("paltform", "android")
|
||||
.addHeaderParams("userToken", "1234343434dfdfd3434")
|
||||
.addHeaderParams("userId", "123445")
|
||||
.build();
|
||||
//builder.addInterceptor(commonInterceptor);
|
||||
|
||||
|
||||
// 创建Retrofit
|
||||
mRetrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(builder.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final RetrofitManager INSTANCE = new RetrofitManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RetrofitServiceManager
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static RetrofitManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应的Service
|
||||
*
|
||||
* @param service Service 的 class
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T> T create(Class<T> service) {
|
||||
return mRetrofit.create(service);
|
||||
}
|
||||
|
||||
public static Observable call(Observable<?> observable, Observer observer) {
|
||||
observable.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(observer);
|
||||
return observable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.tophold.example.demo.kview.btc.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/26 13:29
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiData<T> implements Serializable{
|
||||
public String status;
|
||||
public String ch;
|
||||
public long ts;
|
||||
public T data;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HuobiData{" +
|
||||
"status='" + status + '\'' +
|
||||
", ch='" + ch + '\'' +
|
||||
", ts=" + ts +
|
||||
", data=" + data +
|
||||
'}';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.tophold.example.demo.kview.btc.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/26 13:31
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiQuote implements Serializable{
|
||||
public long id;
|
||||
public double open;
|
||||
public double close;
|
||||
public double low;
|
||||
public double high;
|
||||
public double amount;
|
||||
public double vol;
|
||||
public double count;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HuobiQuote{" +
|
||||
"id='" + id + '\'' +
|
||||
", open=" + open +
|
||||
", close=" + close +
|
||||
", low=" + low +
|
||||
", high=" + high +
|
||||
", amount=" + amount +
|
||||
", vol=" + vol +
|
||||
", count=" + count +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package com.tophold.example.demo.kview.btc.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/26 13:42
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiSymbol implements Serializable {
|
||||
@SerializedName("base-currency")
|
||||
public String base_currency;
|
||||
@SerializedName("quote-currency")
|
||||
public String quote_currency;
|
||||
@SerializedName("price-precision")
|
||||
public int price_precision;
|
||||
@SerializedName("amount-precision")
|
||||
public int amount_precision;
|
||||
@SerializedName("symbol-partition")
|
||||
public String symbol_partition;
|
||||
|
||||
public HuobiSymbol(String base_currency, String quote_currency, int price_precision, int amount_precision, String symbol_partition) {
|
||||
this.base_currency = base_currency;
|
||||
this.quote_currency = quote_currency;
|
||||
this.price_precision = price_precision;
|
||||
this.amount_precision = amount_precision;
|
||||
this.symbol_partition = symbol_partition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HuobiSymbol{" +
|
||||
"base_currency='" + base_currency + '\'' +
|
||||
", quote_currency='" + quote_currency + '\'' +
|
||||
", price_precision=" + price_precision +
|
||||
", amount_precision=" + amount_precision +
|
||||
", symbol_partition='" + symbol_partition + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.tophold.example.demo.kview.btc.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/26 16:07
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiTab implements Serializable {
|
||||
public HuobiTab.HuobiType mForexType;
|
||||
public String tabName;
|
||||
|
||||
public HuobiTab(HuobiTab.HuobiType forexType, String tabName) {
|
||||
this.mForexType = forexType;
|
||||
this.tabName = tabName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应类型的长度
|
||||
*
|
||||
* @return sencond
|
||||
*/
|
||||
public long getTypeLength() {
|
||||
long len = 0;
|
||||
switch (mForexType) {
|
||||
case _timeShring:
|
||||
len = 60;
|
||||
break;
|
||||
case _1m:
|
||||
len = 60;
|
||||
break;
|
||||
case _5m:
|
||||
len = 5 * 60;
|
||||
break;
|
||||
case _15m:
|
||||
len = 15 * 60;
|
||||
break;
|
||||
case _30m:
|
||||
len = 30 * 60;
|
||||
break;
|
||||
case _60m:
|
||||
len = 60 * 60;
|
||||
break;
|
||||
case _1d:
|
||||
len = 24 * 60 * 60;
|
||||
break;
|
||||
case _1w:
|
||||
len = 7 * 24 * 60 * 60;
|
||||
break;
|
||||
case _1mon:
|
||||
len = 30 * 24 * 60 * 60;
|
||||
break;
|
||||
case _1y:
|
||||
len = 365 * 24 * 60 * 60;
|
||||
break;
|
||||
default:
|
||||
len = 60;
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据mForexType返回接口需要的类型字段
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getType() {
|
||||
String typeMsg = "1min";
|
||||
switch (mForexType) {
|
||||
case _timeShring:
|
||||
typeMsg = "1min";
|
||||
break;
|
||||
case _1m:
|
||||
typeMsg = "1min";
|
||||
break;
|
||||
case _5m:
|
||||
typeMsg = "5min";
|
||||
break;
|
||||
case _15m:
|
||||
typeMsg = "15min";
|
||||
break;
|
||||
case _30m:
|
||||
typeMsg = "30min";
|
||||
break;
|
||||
case _60m:
|
||||
typeMsg = "60min";
|
||||
break;
|
||||
case _1d:
|
||||
typeMsg = "1day";
|
||||
break;
|
||||
case _1w:
|
||||
typeMsg = "1week";
|
||||
break;
|
||||
case _1mon:
|
||||
typeMsg = "1mon";
|
||||
break;
|
||||
case _1y:
|
||||
typeMsg = "1year";
|
||||
break;
|
||||
default:
|
||||
typeMsg = "1min";
|
||||
break;
|
||||
}
|
||||
return typeMsg;
|
||||
}
|
||||
|
||||
public enum HuobiType {
|
||||
_timeShring,
|
||||
_1m,
|
||||
_5m,
|
||||
_15m,
|
||||
_30m,
|
||||
_60m,
|
||||
_1d,
|
||||
_1w,
|
||||
_1mon,
|
||||
_1y
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.tophold.example.demo.kview.btc.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/28 18:39
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiWsQuote implements Serializable{
|
||||
|
||||
/**
|
||||
* ch : market.eosusdt.kline.1min
|
||||
* ts : 1522233524438
|
||||
* tick : {"id":1522233480,"open":6.317,"close":6.3216,"low":6.3091,"high":6.3216,"amount":2024.6227,"vol":12789.80758224,"count":21}
|
||||
*/
|
||||
|
||||
public String ch;
|
||||
public long ts;
|
||||
public TickBean tick;
|
||||
|
||||
public static class TickBean {
|
||||
/**
|
||||
* id : 1522233480
|
||||
* open : 6.317
|
||||
* close : 6.3216
|
||||
* low : 6.3091
|
||||
* high : 6.3216
|
||||
* amount : 2024.6227
|
||||
* vol : 12789.80758224
|
||||
* count : 21
|
||||
*/
|
||||
|
||||
public int id;
|
||||
public double open;
|
||||
public double close;
|
||||
public double low;
|
||||
public double high;
|
||||
public double amount;
|
||||
public double vol;
|
||||
public int count;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,199 @@
|
||||
package com.tophold.example.demo.kview.btc.ui;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.example.utils.NoScrollViewPager;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiSymbol;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiTab;
|
||||
import com.tophold.trade.utils.FormatUtil;
|
||||
import com.tophold.trade.utils.TimeUtils;
|
||||
import com.tophold.trade.view.kview.Quotes;
|
||||
|
||||
public class HuobiActivity extends BaseActivity {
|
||||
public static final String KEY_FOREX = "KEY_FOREX";
|
||||
public static final String KEY_HORIZONTAL = "KEY_HORIZONTAL";
|
||||
private TabLayout mAfTlTablayout;
|
||||
private NoScrollViewPager mAfVpViewpager;
|
||||
|
||||
private LinearLayout mAkvLlContainer;
|
||||
private TextView mAkvTvH;
|
||||
private TextView mAkvTvO;
|
||||
private TextView mAkvTvTime;
|
||||
private TextView mAkvTvL;
|
||||
private TextView mAkvTvC;
|
||||
private TextView mAkvTvP;
|
||||
private TextView af_tv_symbol;
|
||||
private TextView mAkvTvBlank;
|
||||
|
||||
//是否是横屏
|
||||
boolean mIsHorizontal = false;
|
||||
|
||||
private List<HuobiTab> mForexTabList;
|
||||
private List<Fragment> mKViewFragmentList;
|
||||
|
||||
HuobiSymbol mForex;
|
||||
|
||||
@Override
|
||||
protected void getBundleExtras(Bundle extras) {
|
||||
super.getBundleExtras(extras);
|
||||
mForex = (HuobiSymbol) extras.getSerializable(KEY_FOREX);
|
||||
mIsHorizontal = extras.getBoolean(KEY_HORIZONTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (mIsHorizontal) {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);// 隐藏标题
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
|
||||
}
|
||||
setContentView(R.layout.activity_huobi);
|
||||
initView();
|
||||
initData();
|
||||
initAdapter();
|
||||
loadData();
|
||||
initListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (mIsHorizontal) {
|
||||
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
}
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAfTlTablayout = (TabLayout) findViewById(R.id.af_tl_tablayout);
|
||||
mAfVpViewpager = (NoScrollViewPager) findViewById(R.id.af_vp_viewpager);
|
||||
|
||||
mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);
|
||||
mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);
|
||||
mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);
|
||||
mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);
|
||||
mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);
|
||||
mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);
|
||||
mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);
|
||||
mAkvTvBlank = (TextView) findViewById(R.id.af_tv_blank);
|
||||
af_tv_symbol = (TextView) findViewById(R.id.af_tv_symbol);
|
||||
|
||||
if (mIsHorizontal) {
|
||||
af_tv_symbol.setVisibility(View.GONE);
|
||||
mAkvTvBlank.setVisibility(View.GONE);
|
||||
} else {
|
||||
af_tv_symbol.setVisibility(View.VISIBLE);
|
||||
mAkvTvBlank.setVisibility(View.VISIBLE);
|
||||
af_tv_symbol.setText(mForex.base_currency + "/" + mForex.quote_currency);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mForexTabList = new ArrayList<>();
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._timeShring, "分时"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1m, "1分"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._5m, "5分"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._15m, "15分"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._30m, "30分"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._60m, "1小时"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1d, "日K"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1w, "周K"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1mon, "月K"));
|
||||
mForexTabList.add(new HuobiTab(HuobiTab.HuobiType._1y, "年K"));
|
||||
|
||||
mAfTlTablayout.setTabMode(TabLayout.MODE_SCROLLABLE);
|
||||
|
||||
mKViewFragmentList = new ArrayList<>();
|
||||
for (HuobiTab forexTab : mForexTabList) {
|
||||
mKViewFragmentList.add(HuobiFragment.newInstance(forexTab, mForex));
|
||||
}
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
mAfVpViewpager.setAdapter(new HuobiAdapter(getSupportFragmentManager(), mKViewFragmentList, mForexTabList));
|
||||
mAfTlTablayout.setupWithViewPager(mAfVpViewpager);
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void hidenContainer() {
|
||||
mAfTlTablayout.setVisibility(View.VISIBLE);
|
||||
mAkvLlContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void showContanier(Quotes preQuotes, Quotes currentQuotes) {
|
||||
mAfTlTablayout.setVisibility(View.GONE);
|
||||
mAkvLlContainer.setVisibility(View.VISIBLE);
|
||||
int digits = 5;
|
||||
boolean isPositive;
|
||||
String precent;
|
||||
double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;
|
||||
isPositive = dis >= 0;
|
||||
precent = FormatUtil.formatBySubString(dis, 2);
|
||||
precent += "%";
|
||||
|
||||
//
|
||||
mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));
|
||||
mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));
|
||||
mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));
|
||||
mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));
|
||||
mAkvTvP.setText(precent);
|
||||
mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat("MM-dd HH:mm")));
|
||||
|
||||
if (isPositive) {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
} else {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMyColor(@ColorRes int colorId) {
|
||||
return getResources().getColor(colorId);
|
||||
}
|
||||
|
||||
public void showHorizontal(View view) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_HORIZONTAL, true);
|
||||
bundle.putSerializable(KEY_FOREX, mForex);
|
||||
go(HuobiActivity.class, bundle);
|
||||
}
|
||||
|
||||
public boolean isHorizontal() {
|
||||
return mIsHorizontal;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.tophold.example.demo.kview.btc.ui;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiTab;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/26 13:37
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiAdapter extends FragmentPagerAdapter {
|
||||
private List<Fragment> mFragmentList;
|
||||
List<HuobiTab> mForexTabList;
|
||||
|
||||
public HuobiAdapter(FragmentManager fm, List<Fragment> fragmentList, List<HuobiTab> mForexTabList) {
|
||||
super(fm);
|
||||
this.mFragmentList = fragmentList;
|
||||
this.mForexTabList = mForexTabList;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return mFragmentList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mFragmentList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return mForexTabList.get(position).tabName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package com.tophold.example.demo.kview.btc.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
import com.tophold.example.base.BaseFragment;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.btc.api.HuobiService;
|
||||
import com.tophold.example.demo.kview.btc.api.HuobiSocketApi;
|
||||
import com.tophold.example.demo.kview.btc.api.RetrofitManager;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiData;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiQuote;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiSymbol;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiTab;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiWsQuote;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
import com.tophold.trade.view.kview.KView;
|
||||
import com.tophold.trade.view.kview.KViewListener;
|
||||
import com.tophold.trade.view.kview.Quotes;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/26 13:36
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class HuobiFragment extends BaseFragment {
|
||||
public static final int DEF_PAGER_SIZE = 1000;
|
||||
private static final String ARG_PARAM1 = "param1";
|
||||
private static final String ARG_PARAM2 = "param2";
|
||||
public static final int DEF_COUNT = 100;
|
||||
private View mRootView;
|
||||
private KView mFkKvKview;
|
||||
HuobiTab mForexTab;
|
||||
HuobiSymbol mForex;
|
||||
|
||||
//net
|
||||
List<Quotes> mQuotesList;
|
||||
|
||||
public HuobiFragment() {
|
||||
|
||||
}
|
||||
|
||||
public static HuobiFragment newInstance(HuobiTab mForexTab, HuobiSymbol forex) {
|
||||
HuobiFragment fragment = new HuobiFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_PARAM1, mForexTab);
|
||||
args.putSerializable(ARG_PARAM2, forex);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mForexTab = (HuobiTab) getArguments().getSerializable(ARG_PARAM1);
|
||||
mForex = (HuobiSymbol) getArguments().getSerializable(ARG_PARAM2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
mRootView = inflater.inflate(R.layout.fragment_huobi, container, false);
|
||||
initView();
|
||||
initData();
|
||||
initAdapter();
|
||||
loadData();
|
||||
initListener();
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
loadKLineData(null, false);
|
||||
|
||||
subKLineData();
|
||||
}
|
||||
|
||||
private void subKLineData() {
|
||||
HuobiSocketApi.subKLine(mForex.base_currency + mForex.quote_currency, mForexTab.getTypeLength() * 1000, true);
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mFkKvKview = (KView) mRootView.findViewById(R.id.fk_kv_kview);
|
||||
|
||||
mFkKvKview.setDigit(5);
|
||||
|
||||
if (mForexTab.mForexType == HuobiTab.HuobiType._timeShring) {
|
||||
mFkKvKview.setShowTimSharing(true);
|
||||
} else {
|
||||
mFkKvKview.setShowTimSharing(false);
|
||||
}
|
||||
|
||||
if (((HuobiActivity) getActivity()).isHorizontal()) {
|
||||
mFkKvKview.setShowMinor(true);
|
||||
mFkKvKview.setShowVol(true);
|
||||
} else {
|
||||
mFkKvKview.setShowMinor(false);
|
||||
mFkKvKview.setShowVol(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mQuotesList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
|
||||
}
|
||||
|
||||
private void loadKLineData(String start_time, final boolean isLoadMore) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
String symbol = mForex.base_currency + "" + mForex.quote_currency;
|
||||
map.put("symbol", symbol);
|
||||
map.put("period", mForexTab.getType());
|
||||
map.put("size", DEF_PAGER_SIZE);
|
||||
//if (start_time != null) map.put("st", start_time);
|
||||
call(RetrofitManager.getInstance().create(HuobiService.class).chartQuotes(map), new Observer<HuobiData<List<HuobiQuote>>>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
unSubscription(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(HuobiData<List<HuobiQuote>> huobiData) {
|
||||
|
||||
String status = huobiData.status;
|
||||
if (!"ok".equals(status)) {
|
||||
Toast.makeText(mContext, "数据获取失败...", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
List<HuobiQuote> data = huobiData.data;
|
||||
if (StringUtils.isEmpty(data)) {
|
||||
Toast.makeText(mContext, "数据为空...", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
adapterData(data);
|
||||
|
||||
drawKView(isLoadMore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void drawKView(boolean isLoadMore) {
|
||||
if (!isLoadMore) {
|
||||
mFkKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {
|
||||
@Override
|
||||
public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {
|
||||
((HuobiActivity) getActivity()).showContanier(preQuotes, currentQuotes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnLongTouch() {
|
||||
((HuobiActivity) getActivity()).hidenContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void needLoadMore() {
|
||||
if (StringUtils.isEmpty(mQuotesList)) {
|
||||
mFkKvKview.loadMoreNoData();
|
||||
return;
|
||||
}
|
||||
Quotes quotes = mQuotesList.get(0);
|
||||
String showTime = quotes.getShowTime();
|
||||
//loadKLineData(showTime, true);火币不支持分页
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mFkKvKview.loadKViewData(mQuotesList);
|
||||
}
|
||||
}
|
||||
|
||||
private void adapterData(List<HuobiQuote> huobiQuoteList) {
|
||||
|
||||
Collections.reverse(huobiQuoteList);
|
||||
|
||||
List<Quotes> quotesList = new ArrayList<>();
|
||||
for (HuobiQuote huobiQuote : huobiQuoteList) {
|
||||
Quotes quotes = new Quotes(huobiQuote.open, huobiQuote.high, huobiQuote.low, huobiQuote.close, huobiQuote.id * 1000, huobiQuote.amount);
|
||||
quotesList.add(quotes);
|
||||
}
|
||||
mQuotesList.addAll(0, quotesList);//注意时序问题
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBindEventBusHere() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onReviceWsQuotes(HuobiWsQuote huobiWsQuote) {
|
||||
if (huobiWsQuote == null || huobiWsQuote.tick == null) return;
|
||||
//返回的数据真实醉了。。。
|
||||
String ch = huobiWsQuote.ch;
|
||||
String[] split = ch.split("\\.");
|
||||
String symbol = split[1];
|
||||
String lineType = split[3];
|
||||
if (!symbol.equals(mForex.base_currency + mForex.quote_currency)) return;
|
||||
if (!lineType.equals(mForexTab.getType())) return;
|
||||
HuobiWsQuote.TickBean tick = huobiWsQuote.tick;
|
||||
Quotes quotes = new Quotes(tick.open, tick.high, tick.low, tick.close, huobiWsQuote.ts);
|
||||
|
||||
mFkKvKview.pushKViewData(quotes, mForexTab.getTypeLength() * 1000);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
HuobiSocketApi.subKLine(mForex.base_currency + mForex.quote_currency, mForexTab.getTypeLength() * 1000, false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package com.tophold.example.demo.kview.btc.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||
import com.chad.library.adapter.base.BaseViewHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.btc.api.HuobiService;
|
||||
import com.tophold.example.demo.kview.btc.api.RetrofitManager;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiData;
|
||||
import com.tophold.example.demo.kview.btc.model.HuobiSymbol;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
|
||||
public class HuobiListActivity extends BaseActivity {
|
||||
|
||||
RecyclerView mAflRlListview;
|
||||
BaseQuickAdapter<HuobiSymbol, BaseViewHolder> mQuickAdapter;
|
||||
List<HuobiSymbol> mForexList;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_huobi_list);
|
||||
initView();
|
||||
initData();
|
||||
initAdapter();
|
||||
loadData();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAflRlListview = (RecyclerView) findViewById(R.id.afl_rl_listview);
|
||||
Toast.makeText(mContext, "请稍后,在拉取列表...", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mForexList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
mQuickAdapter = new BaseQuickAdapter<HuobiSymbol, BaseViewHolder>(R.layout.item_activity_huobi_list, mForexList) {
|
||||
@Override
|
||||
protected void convert(BaseViewHolder helper, HuobiSymbol item) {
|
||||
helper.setText(R.id.iafl_tv_znName, item.base_currency + "/" + item.quote_currency);
|
||||
helper.setText(R.id.iafl_tv_enName, item.quote_currency);
|
||||
helper.setText(R.id.iafl_tv_part, item.symbol_partition);
|
||||
}
|
||||
};
|
||||
mAflRlListview.setLayoutManager(new LinearLayoutManager(mContext));
|
||||
mAflRlListview.setAdapter(mQuickAdapter);
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
call(RetrofitManager.getInstance().create(HuobiService.class).getSymbolList(map), new Observer<HuobiData<List<HuobiSymbol>>>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
unSubscription(d);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(HuobiData<List<HuobiSymbol>> huobiData) {
|
||||
String status = huobiData.status;
|
||||
if (!"ok".equals(status)) {
|
||||
Toast.makeText(mContext, "数据获取失败...", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
List<HuobiSymbol> data = huobiData.data;
|
||||
if (StringUtils.isEmpty(data)) {
|
||||
Toast.makeText(mContext, "数据为空...", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
mForexList.addAll(data);
|
||||
|
||||
//排序操作
|
||||
Collections.sort(mForexList, (o1, o2) -> {
|
||||
if (!o1.symbol_partition.equals(o2.symbol_partition))
|
||||
return -o1.symbol_partition.compareTo(o2.symbol_partition);
|
||||
if (!o1.quote_currency.equals(o2.quote_currency))
|
||||
return -o1.quote_currency.compareTo(o2.quote_currency);
|
||||
return 0;
|
||||
});
|
||||
|
||||
mQuickAdapter.notifyLoadMoreToLoading();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
Log.d(TAG, "onComplete: ");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mQuickAdapter.setOnItemClickListener((adapter, v, p) -> {
|
||||
HuobiSymbol forex = mForexList.get(p);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(HuobiActivity.KEY_FOREX, forex);
|
||||
go(HuobiActivity.class, bundle);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
package com.tophold.example.demo.kview.forex;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 14:16
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class ForexTab implements Serializable {
|
||||
public ForexType mForexType;
|
||||
public String tabName;
|
||||
|
||||
public ForexTab(ForexType forexType, String tabName) {
|
||||
this.mForexType = forexType;
|
||||
this.tabName = tabName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应类型的长度
|
||||
*
|
||||
* @return sencond
|
||||
*/
|
||||
public long getTypeLength() {
|
||||
long len = 0;
|
||||
switch (mForexType) {
|
||||
case _timeShring:
|
||||
len = 60;
|
||||
break;
|
||||
case _1m:
|
||||
len = 60;
|
||||
break;
|
||||
case _5m:
|
||||
len = 5 * 60;
|
||||
break;
|
||||
case _15m:
|
||||
len = 15 * 60;
|
||||
break;
|
||||
case _30m:
|
||||
len = 30 * 60;
|
||||
break;
|
||||
case _1h:
|
||||
len = 60 * 60;
|
||||
break;
|
||||
case _4h:
|
||||
len = 4 * 60 * 60;
|
||||
break;
|
||||
case _1d:
|
||||
len = 24 * 60 * 60;
|
||||
break;
|
||||
case _1w:
|
||||
len = 7 * 24 * 60 * 60;
|
||||
break;
|
||||
case _1mon:
|
||||
len = 30 * 24 * 60 * 60;
|
||||
break;
|
||||
default:
|
||||
len = 60;
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据mForexType返回接口需要的类型字段
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public String getType() {
|
||||
String typeMsg = "1m";
|
||||
switch (mForexType) {
|
||||
case _timeShring:
|
||||
typeMsg = "1m";
|
||||
break;
|
||||
case _1m:
|
||||
typeMsg = "1m";
|
||||
break;
|
||||
case _5m:
|
||||
typeMsg = "5m";
|
||||
break;
|
||||
case _15m:
|
||||
typeMsg = "15m";
|
||||
break;
|
||||
case _30m:
|
||||
typeMsg = "30m";
|
||||
break;
|
||||
case _1h:
|
||||
typeMsg = "1h";
|
||||
break;
|
||||
case _4h:
|
||||
typeMsg = "4h";
|
||||
break;
|
||||
case _1d:
|
||||
typeMsg = "1d";
|
||||
break;
|
||||
case _1w:
|
||||
typeMsg = "1w";
|
||||
break;
|
||||
case _1mon:
|
||||
typeMsg = "1mon";
|
||||
break;
|
||||
default:
|
||||
typeMsg = "1m";
|
||||
break;
|
||||
}
|
||||
return typeMsg;
|
||||
}
|
||||
|
||||
public enum ForexType {
|
||||
_timeShring,
|
||||
_1m,
|
||||
_5m,
|
||||
_15m,
|
||||
_30m,
|
||||
_1h,
|
||||
_4h,
|
||||
_1d,
|
||||
_1w,
|
||||
_1mon
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
package com.tophold.example.demo.kview.forex.api;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.WebSocketListener;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import com.tophold.example.BuildConfig;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:15
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class ForexWebSocket {
|
||||
public static final String TAG = ForexWebSocket.class.getSimpleName();
|
||||
private static final int DEFAULT_TIME_OUT = 5;//超时时间 5s
|
||||
private static final int DEFAULT_READ_TIME_OUT = 10;
|
||||
//temp quotes
|
||||
private static final String BASE_URL = "http://***:8990/websocket";
|
||||
private static final String TOKEN="eyJ0eXAiOiJKV1QiLCJhbGc***Y2NvdW50SWQiOiJFVVI2MTQxLjAwMSIsImlhdCI6MTUyMjgxOTE0NiwiZXhwIjoxNTIzNDIzOTQ2fQ.je5e76RSNh07ZYtu3_yOA8BsBl_wH0_tkqxlgX5hhww";
|
||||
|
||||
Request mRequest;
|
||||
okhttp3.WebSocket mWebSocket;
|
||||
OkHttpClient client;
|
||||
boolean isConnctted = false;
|
||||
|
||||
private ForexWebSocket() {
|
||||
// 创建 OKHttpClient
|
||||
OkHttpClient.Builder builder = new OkHttpClient().newBuilder();
|
||||
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
|
||||
builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间
|
||||
builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间
|
||||
builder.retryOnConnectionFailure(true);//失败重试
|
||||
|
||||
//DEBUG模式下 添加日志拦截器
|
||||
if (BuildConfig.DEBUG) {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
builder.addInterceptor(interceptor);
|
||||
}
|
||||
|
||||
// 添加公共参数拦截器
|
||||
HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
|
||||
.addHeaderParams("paltform", "android")
|
||||
.addHeaderParams("userToken", "1234343434dfdfd3434")
|
||||
.addHeaderParams("userId", "123445")
|
||||
.build();
|
||||
builder.addInterceptor(commonInterceptor);
|
||||
|
||||
|
||||
//HuobiWebSocket
|
||||
client = builder.build();
|
||||
}
|
||||
|
||||
public void init() {
|
||||
mRequest = new Request.Builder().header("Sec-WebSocket-Protocol", TOKEN).url(BASE_URL).build();
|
||||
mWebSocket = client.newWebSocket(mRequest, new WebSocketListener() {
|
||||
@Override
|
||||
public void onOpen(okhttp3.WebSocket webSocket, Response response) {
|
||||
super.onOpen(webSocket, response);
|
||||
isConnctted = true;
|
||||
Log.d(TAG, "onOpen: ");
|
||||
//Toast.makeText(MyApplication.mAppContext, "websocket连接成功...", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(okhttp3.WebSocket webSocket, String text) {
|
||||
super.onMessage(webSocket, text);
|
||||
WebSocketParser.fix2Object(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClosed(okhttp3.WebSocket webSocket, int code, String reason) {
|
||||
super.onClosed(webSocket, code, reason);
|
||||
isConnctted = false;
|
||||
Log.d(TAG, "onClosed,code: " + code + ",reason:" + reason);
|
||||
//Toast.makeText(MyApplication.mAppContext, "websocket关闭...", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(okhttp3.WebSocket webSocket, Throwable t, @Nullable Response response) {
|
||||
super.onFailure(webSocket, t, response);
|
||||
isConnctted = false;
|
||||
//Toast.makeText(MyApplication.mAppContext, "websocket异常:" + response.toString(), Toast.LENGTH_SHORT).show();
|
||||
Log.e(TAG, "onFailure: " + (response != null ? response.toString() : "response==null"));
|
||||
t.printStackTrace();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final ForexWebSocket INSTANCE = new ForexWebSocket();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RetrofitServiceManager
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static ForexWebSocket getInstance() {
|
||||
return ForexWebSocket.SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
package com.tophold.example.demo.kview.forex.api;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
|
||||
/**
|
||||
* 拦截器
|
||||
*
|
||||
* 向请求头里添加公共参数
|
||||
* Created by zhouwei on 16/11/10.
|
||||
*/
|
||||
|
||||
public class HttpCommonInterceptor implements Interceptor {
|
||||
|
||||
private Map<String,String> mHeaderParamsMap = new HashMap<>();
|
||||
public HttpCommonInterceptor() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response intercept(Chain chain) throws IOException {
|
||||
Log.d("HttpCommonInterceptor","add common params");
|
||||
Request oldRequest = chain.request();
|
||||
|
||||
// 添加新的参数,添加到url 中
|
||||
/* HttpUrl.Builder authorizedUrlBuilder = oldRequest.url()
|
||||
.newBuilder()
|
||||
.scheme(oldRequest.url().scheme())
|
||||
.host(oldRequest.url().host());*/
|
||||
|
||||
// 新的请求
|
||||
|
||||
Request.Builder requestBuilder = oldRequest.newBuilder();
|
||||
requestBuilder.method(oldRequest.method(), oldRequest.body());
|
||||
//添加公共参数,添加到header中
|
||||
if(mHeaderParamsMap.size() > 0){
|
||||
for(Map.Entry<String,String> params:mHeaderParamsMap.entrySet()){
|
||||
requestBuilder.header(params.getKey(),params.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
Request newRequest = requestBuilder.build();
|
||||
|
||||
return chain.proceed(newRequest);
|
||||
}
|
||||
|
||||
public static class Builder{
|
||||
HttpCommonInterceptor mHttpCommonInterceptor;
|
||||
|
||||
public Builder(){
|
||||
mHttpCommonInterceptor = new HttpCommonInterceptor();
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, String value){
|
||||
mHttpCommonInterceptor.mHeaderParamsMap.put(key,value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, int value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, float value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, long value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
public Builder addHeaderParams(String key, double value){
|
||||
return addHeaderParams(key, String.valueOf(value));
|
||||
}
|
||||
|
||||
|
||||
public HttpCommonInterceptor build(){
|
||||
return mHttpCommonInterceptor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.tophold.example.demo.kview.forex.api;
|
||||
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.logging.HttpLoggingInterceptor;
|
||||
import retrofit2.Retrofit;
|
||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
||||
import retrofit2.converter.gson.GsonConverterFactory;
|
||||
import com.tophold.example.BuildConfig;
|
||||
|
||||
|
||||
public class RetrofitManager {
|
||||
private static final int DEFAULT_TIME_OUT = 5;//超时时间 5s
|
||||
private static final int DEFAULT_READ_TIME_OUT = 10;
|
||||
//temp quotes
|
||||
private static final String BASE_URL = "http://***:8700/";
|
||||
private Retrofit mRetrofit;
|
||||
|
||||
private RetrofitManager() {
|
||||
// 创建 OKHttpClient
|
||||
OkHttpClient.Builder builder = new OkHttpClient.Builder();
|
||||
builder.connectTimeout(DEFAULT_TIME_OUT, TimeUnit.SECONDS);//连接超时时间
|
||||
builder.writeTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//写操作 超时时间
|
||||
builder.readTimeout(DEFAULT_READ_TIME_OUT, TimeUnit.SECONDS);//读操作超时时间
|
||||
builder.retryOnConnectionFailure(true);//失败重试
|
||||
|
||||
//DEBUG模式下 添加日志拦截器
|
||||
if (BuildConfig.DEBUG) {
|
||||
HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
|
||||
interceptor.setLevel(HttpLoggingInterceptor.Level.HEADERS);
|
||||
builder.addInterceptor(interceptor);
|
||||
}
|
||||
|
||||
// 添加公共参数拦截器
|
||||
HttpCommonInterceptor commonInterceptor = new HttpCommonInterceptor.Builder()
|
||||
.addHeaderParams("paltform", "android")
|
||||
.addHeaderParams("userToken", "1234343434dfdfd3434")
|
||||
.addHeaderParams("userId", "123445")
|
||||
.build();
|
||||
builder.addInterceptor(commonInterceptor);
|
||||
|
||||
|
||||
// 创建Retrofit
|
||||
mRetrofit = new Retrofit.Builder()
|
||||
.baseUrl(BASE_URL)
|
||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.createWithScheduler(Schedulers.io()))
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.client(builder.build())
|
||||
.build();
|
||||
}
|
||||
|
||||
private static class SingletonHolder {
|
||||
private static final RetrofitManager INSTANCE = new RetrofitManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取RetrofitServiceManager
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static RetrofitManager getInstance() {
|
||||
return SingletonHolder.INSTANCE;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取对应的Service
|
||||
*
|
||||
* @param service Service 的 class
|
||||
* @param <T>
|
||||
* @return
|
||||
*/
|
||||
public <T> T create(Class<T> service) {
|
||||
return mRetrofit.create(service);
|
||||
}
|
||||
|
||||
public static Observable call(Observable<?> observable, Observer observer) {
|
||||
observable.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(observer);
|
||||
return observable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.tophold.example.demo.kview.forex.api;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:31
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class WebSocketApi {
|
||||
public static final String TAG = WebSocketApi.class.getSimpleName();
|
||||
|
||||
/**
|
||||
* 订阅价格和取消订阅
|
||||
*
|
||||
* @param isSub true:订阅,false:取消订阅
|
||||
*/
|
||||
public static void subPrice(String symbol, boolean isSub) {
|
||||
String str = "35=V|55=" + symbol + "|263=" + (isSub ? 1 : 2);
|
||||
Log.d(TAG, "subPrice: " + str);
|
||||
if (ForexWebSocket.getInstance().isConnctted) {
|
||||
ForexWebSocket.getInstance().mWebSocket.send(str);
|
||||
} else {
|
||||
Log.e(TAG, "subPrice: websocket未连接");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package com.tophold.example.demo.kview.forex.api;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import org.greenrobot.eventbus.EventBus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.tophold.example.demo.kview.forex.model.WsPrice;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 21:26
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class WebSocketParser {
|
||||
public static final String TAG = WebSocketParser.class.getSimpleName();
|
||||
|
||||
public static void fix2Object(String str) {
|
||||
try {
|
||||
if (str == null || str.length() == 0) return;
|
||||
Log.d(TAG, "fix2Object: " + str);
|
||||
String[] arrs = str.split("\\|");
|
||||
Map<String, String> map = new HashMap<>();
|
||||
for (String arr : arrs) {
|
||||
String[] items = arr.split("=");
|
||||
map.put(items[0], items[1]);
|
||||
}
|
||||
//maping
|
||||
map2Obj(map);
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static void map2Obj(Map<String, String> map) {
|
||||
|
||||
String type = map.get("35");
|
||||
if (type == null) {
|
||||
Log.e(TAG, "map2Obj: type == null");
|
||||
return;
|
||||
}
|
||||
if (type.equals("V")) {
|
||||
map2WsPrice(map);
|
||||
}
|
||||
}
|
||||
|
||||
private static void map2WsPrice(Map<String, String> map) {
|
||||
WsPrice wsPrice = new WsPrice();
|
||||
wsPrice.productName = map.get("55");
|
||||
wsPrice.lastUpdateTime = Long.parseLong(map.get("20068"));
|
||||
wsPrice.bidPrice = Double.parseDouble(map.get("132"));
|
||||
wsPrice.askPrice = Double.parseDouble(map.get("133"));
|
||||
|
||||
EventBus.getDefault().post(wsPrice);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package com.tophold.example.demo.kview.forex.api;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
import retrofit2.http.GET;
|
||||
import retrofit2.http.Path;
|
||||
import retrofit2.http.QueryMap;
|
||||
import com.tophold.example.demo.kview.forex.model.XcfdQuotes;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 11:31
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public interface XcfdService {
|
||||
@GET("/kline/{productCode}/{type}")
|
||||
Observable<List<XcfdQuotes>> chartQuotes(@Path("productCode") String productCode, @Path("type") String type, @QueryMap Map<String, Object> params);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.tophold.example.demo.kview.forex.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 13:03
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class Forex implements Serializable{
|
||||
public String id;
|
||||
public String enName;
|
||||
public String cnName;
|
||||
|
||||
public Forex(String id, String enName, String cnName) {
|
||||
this.id=id;
|
||||
this.enName=enName;
|
||||
this.cnName=cnName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Forex{" +
|
||||
"id='" + id + '\'' +
|
||||
", enName='" + enName + '\'' +
|
||||
", cnName='" + cnName + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package com.tophold.example.demo.kview.forex.model;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2017/12/26 11:38
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class WsPrice {
|
||||
|
||||
//TAG:55,COMMENT:产品
|
||||
@SerializedName("55")
|
||||
public String productName;
|
||||
//TAG:20068,COMMENT:系统最后价格时间
|
||||
@SerializedName("20068")
|
||||
public long lastUpdateTime;
|
||||
//TAG:132,COMMENT:--->对应老系统的卖价
|
||||
@SerializedName("132")
|
||||
public double bidPrice;
|
||||
//TAG:133,COMMENT:--->对应老系统的买价
|
||||
@SerializedName("133")
|
||||
public double askPrice;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WsPrice{" +
|
||||
", productName='" + productName + '\'' +
|
||||
", bidPrice='" + bidPrice + '\'' +
|
||||
", askPrice='" + askPrice + '\'' +
|
||||
"现价:" + ((bidPrice + askPrice) / 2) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.tophold.example.demo.kview.forex.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 11:52
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class XcfdQuotes implements Serializable{
|
||||
public String t; //201802080610
|
||||
public String o;
|
||||
public String h;
|
||||
public String l;
|
||||
public String c;
|
||||
|
||||
public long s;//数据开始时间
|
||||
public long e;//结束时间
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Quotes{" +
|
||||
"t=" + t +
|
||||
", o='" + o + '\'' +
|
||||
", h='" + h + '\'' +
|
||||
", l='" + l + '\'' +
|
||||
", c='" + c + '\'' +
|
||||
", s=" + s +
|
||||
", e=" + e +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.tophold.example.demo.kview.forex.ui;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.ColorRes;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.forex.api.WebSocketApi;
|
||||
import com.tophold.example.demo.kview.forex.model.Forex;
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
import com.tophold.example.utils.NoScrollViewPager;
|
||||
import com.tophold.trade.utils.FormatUtil;
|
||||
import com.tophold.trade.utils.TimeUtils;
|
||||
import com.tophold.example.demo.kview.forex.ForexTab;
|
||||
import com.tophold.trade.view.kview.Quotes;
|
||||
|
||||
public class ForexActivity extends BaseActivity {
|
||||
public static final String KEY_FOREX = "KEY_FOREX";
|
||||
public static final String KEY_HORIZONTAL = "KEY_HORIZONTAL";
|
||||
private TabLayout mAfTlTablayout;
|
||||
private NoScrollViewPager mAfVpViewpager;
|
||||
|
||||
private LinearLayout mAkvLlContainer;
|
||||
private TextView mAkvTvH;
|
||||
private TextView mAkvTvO;
|
||||
private TextView mAkvTvTime;
|
||||
private TextView mAkvTvL;
|
||||
private TextView mAkvTvC;
|
||||
private TextView mAkvTvP;
|
||||
private TextView af_tv_symbol;
|
||||
private TextView mAkvTvBlank;
|
||||
|
||||
//是否是横屏
|
||||
boolean mIsHorizontal = false;
|
||||
|
||||
private List<ForexTab> mForexTabList;
|
||||
private List<Fragment> mKViewFragmentList;
|
||||
|
||||
Forex mForex;
|
||||
|
||||
@Override
|
||||
protected void getBundleExtras(Bundle extras) {
|
||||
super.getBundleExtras(extras);
|
||||
mForex = (Forex) extras.getSerializable(KEY_FOREX);
|
||||
mIsHorizontal = extras.getBoolean(KEY_HORIZONTAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (mIsHorizontal) {
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);// 隐藏标题
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
|
||||
|
||||
WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置全屏
|
||||
}
|
||||
setContentView(R.layout.activity_forex);
|
||||
initView();
|
||||
initData();
|
||||
initAdapter();
|
||||
loadData();
|
||||
initListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
if (mIsHorizontal) {
|
||||
if (getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
}
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAfTlTablayout = (TabLayout) findViewById(R.id.af_tl_tablayout);
|
||||
mAfVpViewpager = (NoScrollViewPager) findViewById(R.id.af_vp_viewpager);
|
||||
|
||||
mAkvLlContainer = (LinearLayout) findViewById(R.id.akv_ll_container);
|
||||
mAkvTvH = (TextView) findViewById(R.id.akv_tv_h);
|
||||
mAkvTvO = (TextView) findViewById(R.id.akv_tv_o);
|
||||
mAkvTvTime = (TextView) findViewById(R.id.akv_tv_time);
|
||||
mAkvTvL = (TextView) findViewById(R.id.akv_tv_l);
|
||||
mAkvTvC = (TextView) findViewById(R.id.akv_tv_c);
|
||||
mAkvTvP = (TextView) findViewById(R.id.akv_tv_p);
|
||||
mAkvTvBlank = (TextView) findViewById(R.id.af_tv_blank);
|
||||
af_tv_symbol = (TextView) findViewById(R.id.af_tv_symbol);
|
||||
|
||||
if (mIsHorizontal) {
|
||||
af_tv_symbol.setVisibility(View.GONE);
|
||||
mAkvTvBlank.setVisibility(View.GONE);
|
||||
} else {
|
||||
af_tv_symbol.setVisibility(View.VISIBLE);
|
||||
mAkvTvBlank.setVisibility(View.VISIBLE);
|
||||
af_tv_symbol.setText(mForex.cnName + "(" + mForex.enName + ")");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mForexTabList = new ArrayList<>();
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._timeShring, "分时"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._1m, "1分"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._5m, "5分"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._15m, "15分"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._30m, "30分"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._1h, "1时"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._4h, "4时"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._1d, "日K"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._1w, "周K"));
|
||||
mForexTabList.add(new ForexTab(ForexTab.ForexType._1mon, "月"));
|
||||
|
||||
mAfTlTablayout.setTabMode(TabLayout.MODE_SCROLLABLE);
|
||||
|
||||
mKViewFragmentList = new ArrayList<>();
|
||||
for (ForexTab forexTab : mForexTabList) {
|
||||
mKViewFragmentList.add(KViewFragment.newInstance(forexTab, mForex));
|
||||
}
|
||||
|
||||
//加载实时价格数据
|
||||
WebSocketApi.subPrice(mForex.enName, true);
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
mAfVpViewpager.setAdapter(new KViewAdapter(getSupportFragmentManager(), mKViewFragmentList, mForexTabList));
|
||||
mAfTlTablayout.setupWithViewPager(mAfVpViewpager);
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void hidenContainer() {
|
||||
mAfTlTablayout.setVisibility(View.VISIBLE);
|
||||
mAkvLlContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void showContanier(Quotes preQuotes, Quotes currentQuotes) {
|
||||
mAfTlTablayout.setVisibility(View.GONE);
|
||||
mAkvLlContainer.setVisibility(View.VISIBLE);
|
||||
int digits = 5;
|
||||
boolean isPositive;
|
||||
String precent;
|
||||
double dis = (currentQuotes.c - preQuotes.c) / currentQuotes.c * 100;
|
||||
isPositive = dis >= 0;
|
||||
precent = FormatUtil.formatBySubString(dis, 2);
|
||||
precent += "%";
|
||||
|
||||
//
|
||||
mAkvTvH.setText(FormatUtil.numFormat(currentQuotes.h, digits));
|
||||
mAkvTvO.setText(FormatUtil.numFormat(currentQuotes.o, digits));
|
||||
mAkvTvL.setText(FormatUtil.numFormat(currentQuotes.l, digits));
|
||||
mAkvTvC.setText(FormatUtil.numFormat(currentQuotes.c, digits));
|
||||
mAkvTvP.setText(precent);
|
||||
mAkvTvTime.setText(TimeUtils.millis2String(currentQuotes.t, new SimpleDateFormat("MM-dd HH:mm")));
|
||||
|
||||
if (isPositive) {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackRed));
|
||||
} else {
|
||||
mAkvTvH.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvO.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvL.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvC.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
mAkvTvP.setTextColor(getMyColor(R.color.color_timeSharing_callBackGreen));
|
||||
}
|
||||
}
|
||||
|
||||
private int getMyColor(@ColorRes int colorId) {
|
||||
return getResources().getColor(colorId);
|
||||
}
|
||||
|
||||
public void showHorizontal(View view) {
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putBoolean(KEY_HORIZONTAL, true);
|
||||
bundle.putSerializable(KEY_FOREX, mForex);
|
||||
go(ForexActivity.class, bundle);
|
||||
}
|
||||
|
||||
public boolean isHorizontal() {
|
||||
return mIsHorizontal;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
WebSocketApi.subPrice(mForex.enName, false);//取消订阅
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package com.tophold.example.demo.kview.forex.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
|
||||
import com.chad.library.adapter.base.BaseQuickAdapter;
|
||||
import com.chad.library.adapter.base.BaseViewHolder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.forex.model.Forex;
|
||||
import com.tophold.example.base.BaseActivity;
|
||||
|
||||
public class ForexListActivity extends BaseActivity {
|
||||
RecyclerView mAflRlListview;
|
||||
BaseQuickAdapter<Forex, BaseViewHolder> mQuickAdapter;
|
||||
List<Forex> mForexList;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_forex_list);
|
||||
initView();
|
||||
initData();
|
||||
initAdapter();
|
||||
loadData();
|
||||
initListener();
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mAflRlListview = (RecyclerView) findViewById(R.id.afl_rl_listview);
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mForexList = new ArrayList<>();
|
||||
mForexList.add(new Forex("1", "EURUSD", "欧元/美元"));
|
||||
mForexList.add(new Forex("2", "USDJPY", "美元/日元"));
|
||||
mForexList.add(new Forex("3", "AUDUSD", "澳元/美元"));
|
||||
mForexList.add(new Forex("4", "GBPUSD", "英镑/美元"));
|
||||
mForexList.add(new Forex("5", "USDCHF", "美元/瑞郎"));
|
||||
mForexList.add(new Forex("6", "USDSGD", "美元/新加坡元"));
|
||||
mForexList.add(new Forex("7", "USDCAD", "美元/加元"));
|
||||
mForexList.add(new Forex("8", "EURJPY", "欧元/日元"));
|
||||
mForexList.add(new Forex("9", "EURGBP", "欧元/英镑"));
|
||||
mForexList.add(new Forex("10", "NZDUSD", "纽元/美元"));
|
||||
mForexList.add(new Forex("11", "GBPJYP", "英镑/日元"));
|
||||
mForexList.add(new Forex("12", "USDMXN", "美元/墨西哥比索"));
|
||||
mForexList.add(new Forex("13", "GOLD", "黄金"));
|
||||
mForexList.add(new Forex("14", "SILVER", "白银"));
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
mQuickAdapter = new BaseQuickAdapter<Forex, BaseViewHolder>(R.layout.item_activity_forex_list, mForexList) {
|
||||
@Override
|
||||
protected void convert(BaseViewHolder helper, Forex item) {
|
||||
helper.setText(R.id.iafl_tv_enName, item.enName);
|
||||
helper.setText(R.id.iafl_tv_znName, item.cnName);
|
||||
}
|
||||
};
|
||||
mAflRlListview.setLayoutManager(new LinearLayoutManager(mContext));
|
||||
mAflRlListview.setAdapter(mQuickAdapter);
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
mQuickAdapter.setOnItemClickListener((adapter, v, p) -> {
|
||||
Forex forex = mForexList.get(p);
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.putSerializable(ForexActivity.KEY_FOREX, forex);
|
||||
go(ForexActivity.class, bundle);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.tophold.example.demo.kview.forex.ui;
|
||||
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentPagerAdapter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.tophold.example.demo.kview.forex.ForexTab;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 14:38
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class KViewAdapter extends FragmentPagerAdapter {
|
||||
private List<Fragment> mFragmentList;
|
||||
List<ForexTab> mForexTabList;
|
||||
|
||||
public KViewAdapter(FragmentManager fm, List<Fragment> fragmentList, List<ForexTab> mForexTabList) {
|
||||
super(fm);
|
||||
this.mFragmentList = fragmentList;
|
||||
this.mForexTabList = mForexTabList;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Fragment getItem(int position) {
|
||||
return mFragmentList.get(position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCount() {
|
||||
return mFragmentList.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getPageTitle(int position) {
|
||||
return mForexTabList.get(position).tabName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,197 @@
|
||||
package com.tophold.example.demo.kview.forex.ui;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import io.reactivex.Observer;
|
||||
import io.reactivex.disposables.Disposable;
|
||||
|
||||
import com.tophold.example.base.BaseFragment;
|
||||
import com.tophold.example.R;
|
||||
import com.tophold.example.demo.kview.forex.api.RetrofitManager;
|
||||
import com.tophold.example.demo.kview.forex.api.XcfdService;
|
||||
import com.tophold.example.demo.kview.forex.model.Forex;
|
||||
import com.tophold.example.demo.kview.forex.model.WsPrice;
|
||||
import com.tophold.example.demo.kview.forex.model.XcfdQuotes;
|
||||
import com.tophold.trade.utils.StringUtils;
|
||||
import com.tophold.example.demo.kview.forex.ForexTab;
|
||||
import com.tophold.trade.view.kview.KView;
|
||||
import com.tophold.trade.view.kview.KViewListener;
|
||||
import com.tophold.trade.view.kview.Quotes;
|
||||
|
||||
public class KViewFragment extends BaseFragment {
|
||||
private static final String ARG_PARAM1 = "param1";
|
||||
private static final String ARG_PARAM2 = "param2";
|
||||
public static final int DEF_COUNT = 100;
|
||||
private View mRootView;
|
||||
private KView mFkKvKview;
|
||||
ForexTab mForexTab;
|
||||
Forex mForex;
|
||||
|
||||
//net
|
||||
List<Quotes> mQuotesList;
|
||||
|
||||
public KViewFragment() {
|
||||
|
||||
}
|
||||
|
||||
public static KViewFragment newInstance(ForexTab mForexTab, Forex forex) {
|
||||
KViewFragment fragment = new KViewFragment();
|
||||
Bundle args = new Bundle();
|
||||
args.putSerializable(ARG_PARAM1, mForexTab);
|
||||
args.putSerializable(ARG_PARAM2, forex);
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
if (getArguments() != null) {
|
||||
mForexTab = (ForexTab) getArguments().getSerializable(ARG_PARAM1);
|
||||
mForex = (Forex) getArguments().getSerializable(ARG_PARAM2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
mRootView = inflater.inflate(R.layout.fragment_kview, container, false);
|
||||
initView();
|
||||
initData();
|
||||
initAdapter();
|
||||
loadData(null, false);
|
||||
initListener();
|
||||
return mRootView;
|
||||
}
|
||||
|
||||
private void initView() {
|
||||
mFkKvKview = (KView) mRootView.findViewById(R.id.fk_kv_kview);
|
||||
|
||||
mFkKvKview.setDigit(5);
|
||||
|
||||
if (mForexTab.mForexType == ForexTab.ForexType._timeShring) {
|
||||
mFkKvKview.setShowTimSharing(true);
|
||||
} else {
|
||||
mFkKvKview.setShowTimSharing(false);
|
||||
}
|
||||
|
||||
if (((ForexActivity) getActivity()).isHorizontal()) {
|
||||
mFkKvKview.setShowMinor(true);
|
||||
} else {
|
||||
mFkKvKview.setShowMinor(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void initData() {
|
||||
mQuotesList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void initAdapter() {
|
||||
|
||||
}
|
||||
|
||||
private void loadData(String start_time, final boolean isLoadMore) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("count", DEF_COUNT);
|
||||
if (start_time != null) map.put("st", start_time);
|
||||
call(RetrofitManager.getInstance().create(XcfdService.class).chartQuotes(mForex.enName, mForexTab.getType(), map), new Observer<List<XcfdQuotes>>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNext(List<XcfdQuotes> xcfdQuotesList) {
|
||||
if (StringUtils.isEmpty(xcfdQuotesList)) {
|
||||
Log.d(TAG, "onNext: 数据为空");
|
||||
return;
|
||||
}
|
||||
adapterData(xcfdQuotesList);
|
||||
|
||||
drawKView(isLoadMore);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Throwable e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(mContext, "" + e.getMessage(), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onComplete() {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void drawKView(boolean isLoadMore) {
|
||||
if (!isLoadMore) {
|
||||
mFkKvKview.setKViewData(mQuotesList, new KViewListener.MasterTouchListener() {
|
||||
@Override
|
||||
public void onLongTouch(Quotes preQuotes, Quotes currentQuotes) {
|
||||
((ForexActivity) getActivity()).showContanier(preQuotes, currentQuotes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnLongTouch() {
|
||||
((ForexActivity) getActivity()).hidenContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void needLoadMore() {
|
||||
if (StringUtils.isEmpty(mQuotesList)) {
|
||||
mFkKvKview.loadMoreNoData();
|
||||
return;
|
||||
}
|
||||
Quotes quotes = mQuotesList.get(0);
|
||||
String showTime = quotes.getShowTime();
|
||||
loadData(showTime, true);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
mFkKvKview.loadKViewData(mQuotesList);
|
||||
}
|
||||
}
|
||||
|
||||
private void adapterData(List<XcfdQuotes> xcfdQuotesList) {
|
||||
List<Quotes> quotesList = new ArrayList<>();
|
||||
for (XcfdQuotes xcfdQuotes : xcfdQuotesList) {
|
||||
Quotes quotes = new Quotes(xcfdQuotes.o, xcfdQuotes.h, xcfdQuotes.l, xcfdQuotes.c, xcfdQuotes.s, xcfdQuotes.e);
|
||||
quotesList.add(quotes);
|
||||
}
|
||||
|
||||
mQuotesList.addAll(0, quotesList);//注意时序问题
|
||||
}
|
||||
|
||||
private void initListener() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBindEventBusHere() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||
public void onRevicePrice(WsPrice wsPrice) {
|
||||
if (wsPrice == null || !wsPrice.productName.equals(mForex.enName)) return;
|
||||
double currPrice = (wsPrice.askPrice + wsPrice.bidPrice) / 2.0;//均价
|
||||
String currPriceStr = String.valueOf(currPrice);
|
||||
|
||||
Quotes quotes = new Quotes(currPriceStr, currPriceStr, currPriceStr, currPriceStr, wsPrice.lastUpdateTime, wsPrice.lastUpdateTime);
|
||||
|
||||
mFkKvKview.pushKViewData(quotes, mForexTab.getTypeLength() * 1000);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package com.tophold.example.demo.pie
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.ColorInt
|
||||
import android.support.v4.content.ContextCompat
|
||||
import com.tophold.example.base.BaseActivity
|
||||
import com.tophold.example.R
|
||||
import com.tophold.trade.view.pie.PieEntrys
|
||||
import kotlinx.android.synthetic.main.activity_pie_chart.*
|
||||
|
||||
class PieChartActivity : BaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_pie_chart)
|
||||
|
||||
initPieChart()
|
||||
|
||||
loadPieChart()
|
||||
}
|
||||
|
||||
private fun loadPieChart() {
|
||||
val pieEntrysList: MutableList<PieEntrys> = ArrayList()
|
||||
pieEntrysList.add(PieEntrys(10f, "80%", getColorId(R.color.trade_analyze_pie_1), false, "澳元/美元"))
|
||||
pieEntrysList.add(PieEntrys(50f, "胜率 86.96%", getColorId(R.color.trade_analyze_pie_2), true, "英镑/美元"))
|
||||
pieEntrysList.add(PieEntrys(1f, "60.71%", getColorId(R.color.trade_analyze_pie_3), false, "黄金"))
|
||||
pieEntrysList.add(PieEntrys(1f, "76.47%", getColorId(R.color.trade_analyze_pie_4), false, "欧元/美元"))
|
||||
|
||||
hatab_tapc_chart.pieEntryList = pieEntrysList
|
||||
}
|
||||
|
||||
private fun initPieChart() {
|
||||
hatab_tapc_chart.basePaddingTop = 40f
|
||||
hatab_tapc_chart.basePaddingBottom = 40f
|
||||
}
|
||||
|
||||
@ColorInt
|
||||
private fun getColorId(colorId: Int): Int {
|
||||
return ContextCompat.getColor(mContext,colorId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
package com.tophold.example.demo.seekbar
|
||||
|
||||
import android.os.Bundle
|
||||
import android.support.annotation.NonNull
|
||||
import com.tophold.example.base.BaseActivity
|
||||
import com.tophold.example.R
|
||||
import kotlinx.android.synthetic.main.activity_double_thumb_seek_bar.*
|
||||
import com.tophold.trade.utils.RenderUtils.dp2px
|
||||
import com.tophold.trade.view.seekbar.DoubleTumb
|
||||
|
||||
|
||||
class DoubleThumbSeekBarActivity : BaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(R.layout.activity_double_thumb_seek_bar)
|
||||
renderView1()
|
||||
}
|
||||
|
||||
private fun renderView1() {
|
||||
/**
|
||||
* def
|
||||
*/
|
||||
am_dtsv_seek0.init(loadTpSeekBar())
|
||||
|
||||
/**
|
||||
* 加载单个thumb,从左边开始且最小值从最左边开始
|
||||
*/
|
||||
am_dtsv_seek1.init(loadTpSeekBar(
|
||||
false, -44.0, 66.0, true, 4,
|
||||
true, false, 0.2, greenA = false))
|
||||
/**
|
||||
* 单个thumb,从右边开始且从左边开始最小值
|
||||
*/
|
||||
am_dtsv_seek2.init(loadTpSeekBar(
|
||||
false, -44.0, 66.0, true, 4,
|
||||
false, true, 0.2, greenA = true))
|
||||
/**
|
||||
* 双thumb同向,最小值从左边开始
|
||||
*/
|
||||
am_dtsv_seek3.init(loadTpSeekBar(
|
||||
true, -44.0, 66.0, true, 4,
|
||||
true, true, 0.2, false,
|
||||
true, true, 0.33, false))
|
||||
/**
|
||||
* 双thumb同向,最小值从右边开始
|
||||
*/
|
||||
am_dtsv_seek4.init(loadTpSeekBar(
|
||||
true, -44.0, 66.0, false, 4,
|
||||
false, true, 0.2, true,
|
||||
false, true, 0.33, true))
|
||||
|
||||
/**
|
||||
* 交叉方式显示
|
||||
*/
|
||||
am_dtsv_seek5.init(loadTpSeekBar(
|
||||
true, -44.0, 66.0, false, 4,
|
||||
true, true, 0.2, false,
|
||||
false, true, 0.33, true))
|
||||
}
|
||||
|
||||
/**
|
||||
* @param doubleThumb 是否启动双thumb
|
||||
* @param min 最小值
|
||||
* @param max 最大值
|
||||
* @param minFromLeft 最小值是否从左边开始(注意和从哪边开始滑动无关)
|
||||
* @param digit 格式化的小数位数
|
||||
*
|
||||
* @param fromLeftA 是否从左边开始滑动
|
||||
* @param showTipsA 是否实时展示当前值
|
||||
* @param progressA 默认进度(0~1)
|
||||
* @param greenA thumbA的背景色
|
||||
*
|
||||
* @param fromLeftB 是否从左边开始滑动
|
||||
* @param showTipsB 是否实时展示当前值
|
||||
* @param progressB 默认进度(0~1)
|
||||
* @param greenB thumbA的背景色
|
||||
*
|
||||
*/
|
||||
@NonNull
|
||||
fun loadTpSeekBar(doubleThumb: Boolean = false, min: Double = 0.0, max: Double = 100.0, minFromLeft: Boolean = true, digit: Int = 2,
|
||||
fromLeftA: Boolean = true, showTipsA: Boolean = true, progressA: Double = 0.0, greenA: Boolean = false,
|
||||
fromLeftB: Boolean = true, showTipsB: Boolean = true, progressB: Double = 0.0, greenB: Boolean = false): DoubleTumb {
|
||||
|
||||
val thumbAForeground = if (!greenA) {
|
||||
getCompatColor(R.color.dtsb_thumb1Color)
|
||||
} else {
|
||||
getCompatColor(R.color.dtsb_thumb2Color)
|
||||
|
||||
}
|
||||
|
||||
val thumbADrawable = if (!greenA) {
|
||||
getCompatDrawable(R.drawable.layer_seekbar_thumb_red)
|
||||
} else {
|
||||
getCompatDrawable(R.drawable.layer_seekbar_thumb_green)
|
||||
}
|
||||
|
||||
val thumbA = DoubleTumb.Thumb(thumbAForeground)
|
||||
thumbA.progress = progressA//默认位置,百分比值(0~1)
|
||||
thumbA.mFromLeft = fromLeftA//是否从左边开始滑动
|
||||
thumbA.mShowTips = showTipsA
|
||||
thumbA.setmThumb(thumbADrawable)
|
||||
thumbA.setmThumbWidth(dp2px(mContext, 20f))
|
||||
thumbA.setmThumbHight(dp2px(mContext, 25f))
|
||||
|
||||
var thumbB: DoubleTumb.Thumb? = null
|
||||
//复杂模式显示两个thumb
|
||||
if (doubleThumb) {
|
||||
val thumbBForeground = if (!greenB) {
|
||||
getCompatColor(R.color.dtsb_thumb11Color)
|
||||
} else {
|
||||
getCompatColor(R.color.dtsb_thumb22Color)
|
||||
|
||||
}
|
||||
val thumbBDrawable = if (!greenB) {
|
||||
getCompatDrawable(R.drawable.layer_seekbar_thumb_red)
|
||||
} else {
|
||||
getCompatDrawable(R.drawable.layer_seekbar_thumb_green)
|
||||
}
|
||||
thumbB = DoubleTumb.Thumb(thumbBForeground)
|
||||
thumbB.progress = progressB
|
||||
thumbB.mFromLeft = fromLeftB
|
||||
thumbB.mShowTips = showTipsB
|
||||
thumbB.setmThumb(thumbBDrawable)
|
||||
thumbB.setmThumbWidth(dp2px(mContext, 20f))
|
||||
thumbB.setmThumbHight(dp2px(mContext, 25f))
|
||||
}
|
||||
|
||||
val doubleTumb = DoubleTumb(min, max,
|
||||
dp2px(mContext, 4f).toFloat(),
|
||||
getCompatColor(R.color.dtsb_bgColor),
|
||||
thumbA,
|
||||
thumbB)
|
||||
//注意这里!!!
|
||||
doubleTumb.mMinLeft = minFromLeft
|
||||
doubleTumb.mDigit = digit
|
||||
//根据总高度取设置
|
||||
doubleTumb.mLineTop = dp2px(mContext, 40f)
|
||||
doubleTumb.mLineBottom = dp2px(mContext, 10f)
|
||||
doubleTumb.mLineLeft = dp2px(mContext, 8f)
|
||||
doubleTumb.mLineRight = dp2px(mContext, 8f)
|
||||
|
||||
return doubleTumb
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package com.tophold.example.utils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>GSON工具类</p>
|
||||
*
|
||||
* @author
|
||||
* @version $Id: GsonUtil.java
|
||||
*/
|
||||
public class GsonUtil {
|
||||
|
||||
private static Gson gson = null;
|
||||
private static Gson prettyGson = null;
|
||||
|
||||
static {
|
||||
gson = new GsonBuilder()
|
||||
.setDateFormat("yyyy-MM-dd HH:mm:ss").create();
|
||||
prettyGson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
}
|
||||
|
||||
/**
|
||||
* 小写下划线的格式解析JSON字符串到对象
|
||||
* <p>例如 is_success->isSuccess</p>
|
||||
*
|
||||
* @param json
|
||||
* @param classOfT
|
||||
* @return
|
||||
*/
|
||||
public static <T> T fromJsonUnderScoreStyle(String json, Class<T> classOfT) {
|
||||
return gson.fromJson(json, classOfT);
|
||||
}
|
||||
|
||||
/**
|
||||
* JSON字符串转为Map<String,String>
|
||||
*
|
||||
* @param json
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
public static <T> T fronJson2Map(String json) {
|
||||
return gson.fromJson(json, new TypeToken<Map<String, String>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
/**
|
||||
* 小写下划线的格式将对象转换成JSON字符串
|
||||
*
|
||||
* @param src
|
||||
* @return
|
||||
*/
|
||||
public static String toJson(Object src) {
|
||||
return gson.toJson(src);
|
||||
}
|
||||
|
||||
public static String toPrettyString(Object src) {
|
||||
return prettyGson.toJson(src);
|
||||
}
|
||||
|
||||
public static <T> T fromJson2Object(String src, Class<T> t) {
|
||||
return gson.fromJson(src, t);
|
||||
}
|
||||
|
||||
public static <T> T fromJson2Object(String src, Type typeOfT) {
|
||||
return gson.fromJson(src, typeOfT);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package com.tophold.example.utils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
/**
|
||||
* ============================================================
|
||||
* 作 者 : wgyscsf@163.com
|
||||
* 创建日期 :2018/03/22 14:55
|
||||
* 描 述 :
|
||||
* ============================================================
|
||||
**/
|
||||
public class NoScrollViewPager extends ViewPager {
|
||||
public NoScrollViewPager(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public NoScrollViewPager(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(MotionEvent arg0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onInterceptTouchEvent(MotionEvent arg0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package com.tophold.example.utils;
|
||||
|
||||
import io.reactivex.FlowableTransformer;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.ObservableTransformer;
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||
import io.reactivex.schedulers.Schedulers;
|
||||
|
||||
/**
|
||||
* Created by chao.qu at 2017/10/20
|
||||
*
|
||||
* @author quchao
|
||||
*/
|
||||
|
||||
public class RxUtils {
|
||||
|
||||
/**
|
||||
* 统一线程处理
|
||||
*
|
||||
* @param <T> 指定的泛型类型
|
||||
* @return FlowableTransformer
|
||||
*/
|
||||
public static <T> FlowableTransformer<T, T> rxFlSchedulerHelper() {
|
||||
return flowable -> flowable.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一线程处理
|
||||
*
|
||||
* @param <T> 指定的泛型类型
|
||||
* @return ObservableTransformer
|
||||
*/
|
||||
public static <T> ObservableTransformer<T, T> rxSchedulerHelper() {
|
||||
return observable -> observable.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一线程处理
|
||||
*
|
||||
* @param <T> 指定的泛型类型
|
||||
* @return ObservableTransformer
|
||||
*/
|
||||
public static <T> ObservableTransformer<T, T> rxApiSchedulerHelper() {
|
||||
return observable -> observable.subscribeOn(Schedulers.io())
|
||||
.unsubscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread());
|
||||
}
|
||||
|
||||
/**
|
||||
* 得到 Observable
|
||||
*
|
||||
* @param <T> 指定的泛型类型
|
||||
* @return Observable
|
||||
*/
|
||||
private static <T> Observable<T> createData(final T t) {
|
||||
return Observable.create(emitter -> {
|
||||
try {
|
||||
emitter.onNext(t);
|
||||
emitter.onComplete();
|
||||
} catch (Exception e) {
|
||||
emitter.onError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.7 KiB |
@@ -0,0 +1,11 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<shape>
|
||||
<size
|
||||
android:height="20dp"
|
||||
android:width="18dp"/>
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:drawable="@drawable/ico_sl"/>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,11 @@
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
|
||||
<item>
|
||||
<shape>
|
||||
<size
|
||||
android:height="20dp"
|
||||
android:width="18dp"/>
|
||||
<solid android:color="@android:color/transparent" />
|
||||
</shape>
|
||||
</item>
|
||||
<item android:drawable="@drawable/ico_tp"/>
|
||||
</layer-list>
|
||||
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.tophold.trade.view.seekbar.DoubleThumbSeekBar
|
||||
android:id="@+id/am_dtsv_seek0"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="#fff" />
|
||||
|
||||
<com.tophold.trade.view.seekbar.DoubleThumbSeekBar
|
||||
android:id="@+id/am_dtsv_seek1"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="#fff" />
|
||||
|
||||
|
||||
<com.tophold.trade.view.seekbar.DoubleThumbSeekBar
|
||||
android:id="@+id/am_dtsv_seek2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="#fff" />
|
||||
|
||||
<com.tophold.trade.view.seekbar.DoubleThumbSeekBar
|
||||
android:id="@+id/am_dtsv_seek3"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="#fff" />
|
||||
|
||||
<com.tophold.trade.view.seekbar.DoubleThumbSeekBar
|
||||
android:id="@+id/am_dtsv_seek4"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="#fff" />
|
||||
|
||||
<com.tophold.trade.view.seekbar.DoubleThumbSeekBar
|
||||
android:id="@+id/am_dtsv_seek5"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="54dp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:layout_marginRight="4dp"
|
||||
android:background="#fff" />
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
|
||||
@@ -0,0 +1,205 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/af_tl_tablayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
app:tabIndicatorColor="@color/color_tb_indicator"
|
||||
app:tabSelectedTextColor="@color/color_tb_selectedTxt"
|
||||
app:tabTextColor="@color/color_tb_Txt"
|
||||
/>
|
||||
|
||||
<!--按下的指标显示-->
|
||||
<LinearLayout
|
||||
android:id="@+id/akv_ll_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="#e7e3e3"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="4dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="高:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_h"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="开:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_o"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="低:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_l"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="收:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_c"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="幅:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_p"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="#8f8d8d"/>
|
||||
|
||||
<com.tophold.example.utils.NoScrollViewPager
|
||||
android:id="@+id/af_vp_viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/af_tv_symbol"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:text="欧元/美元(USDCAD)"
|
||||
android:gravity="center"
|
||||
android:background="#a7a4a4"/>
|
||||
<TextView
|
||||
android:id="@+id/af_tv_blank"
|
||||
android:onClick="showHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="#cccccc"
|
||||
android:gravity="center"
|
||||
android:text="业务模块(单击这里进入横屏)"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/afl_rl_listview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:background="#000"
|
||||
|
||||
>
|
||||
<com.tophold.trade.view.fund.FundView
|
||||
android:id="@+id/af_fv_fundview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"
|
||||
android:background="#fff"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,205 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<android.support.design.widget.TabLayout
|
||||
android:id="@+id/af_tl_tablayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
app:tabIndicatorColor="@color/color_tb_indicator"
|
||||
app:tabSelectedTextColor="@color/color_tb_selectedTxt"
|
||||
app:tabTextColor="@color/color_tb_Txt"
|
||||
/>
|
||||
|
||||
<!--按下的指标显示-->
|
||||
<LinearLayout
|
||||
android:id="@+id/akv_ll_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:background="#e7e3e3"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="4dp"
|
||||
android:visibility="gone">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="高:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_h"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="开:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_o"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="低:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_l"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="收:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_c"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="幅:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_p"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:background="#8f8d8d"/>
|
||||
|
||||
<com.tophold.example.utils.NoScrollViewPager
|
||||
android:id="@+id/af_vp_viewpager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/af_tv_symbol"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="40dp"
|
||||
android:text="欧元/美元(USDCAD)"
|
||||
android:gravity="center"
|
||||
android:background="#a7a4a4"/>
|
||||
<TextView
|
||||
android:id="@+id/af_tv_blank"
|
||||
android:onClick="showHorizontal"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="#cccccc"
|
||||
android:gravity="center"
|
||||
android:text="业务模块(单击这里进入横屏)"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:background="#d9cfcf">
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/afl_rl_listview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="kViewVertical"
|
||||
android:text="K线图竖屏(本地数据)" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="kViewHorizontal"
|
||||
android:text="K线图横屏(本地数据)" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="kViewEvaluation"
|
||||
android:text="外汇Demo(可能因为API限制显示不了)"
|
||||
android:textAllCaps="false" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="btnDemo"
|
||||
android:text="数字货币demo(火币API)"
|
||||
android:textAllCaps="false" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,172 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!--按下的指标显示-->
|
||||
<LinearLayout
|
||||
android:id="@+id/akv_ll_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#e7e3e3"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="4dp"
|
||||
android:visibility="invisible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="高:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_h"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="开:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_o"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="20dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="低:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_l"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="收:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_c"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="幅:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_p"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<com.tophold.trade.view.kview.KView
|
||||
android:id="@+id/akv_kv_kview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
android:onClick="showCandle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="30dp"
|
||||
android:text="点击展示蜡烛图"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,192 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!--按下的指标显示-->
|
||||
<LinearLayout
|
||||
android:id="@+id/akv_ll_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginTop="20dp"
|
||||
android:background="#e7e3e3"
|
||||
android:orientation="vertical"
|
||||
android:paddingTop="4dp"
|
||||
android:visibility="invisible">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="25dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="高:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_h"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="开:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_o"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="25dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="低:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_l"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="收:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_c"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="幅:"
|
||||
android:textColor="#000"
|
||||
android:textSize="12dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/akv_tv_p"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/string_placeHold"
|
||||
android:textColor="#f00"
|
||||
android:textSize="12dp"/>
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<com.tophold.trade.view.kview.KView
|
||||
android:id="@+id/akv_kv_kview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="300dp"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="45dp"
|
||||
android:layout_marginTop="100dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Button
|
||||
android:id="@+id/akv_btn_showCandle"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_weight="1"
|
||||
android:onClick="showCandle"
|
||||
android:text="点击展示蜡烛图"/>
|
||||
|
||||
<View
|
||||
android:layout_width="10dp"
|
||||
android:layout_height="match_parent"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/akv_btn_showMinnor"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="45dp"
|
||||
android:layout_weight="1"
|
||||
android:onClick="showMinor"
|
||||
android:text="点击不显示副图"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/version"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="top"
|
||||
android:gravity="center"
|
||||
android:padding="16dp"
|
||||
android:text="verisonName:1.4,versionCode(git head):"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="100dp"
|
||||
android:onClick="fundView"
|
||||
android:text="去看自定义基金View Demo"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:textAllCaps="false"
|
||||
android:onClick="kViewDemo"
|
||||
android:text="去看KView Demo"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="onPieTest"
|
||||
android:text="去看PieChart饼图 Demo"
|
||||
android:textAllCaps="false"
|
||||
/>
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="onSeekBarTest"
|
||||
android:text="去看DoubleThumbSeekBar Demo"
|
||||
android:textAllCaps="false" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="10dp"
|
||||
android:onClick="onRx"
|
||||
android:text="去看Rx"
|
||||
android:textAllCaps="false" />
|
||||
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#dedbdb"
|
||||
android:gravity="center">
|
||||
|
||||
|
||||
<com.tophold.trade.view.pie.PieChartView
|
||||
android:id="@+id/hatab_tapc_chart"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="215dp"
|
||||
android:background="#fff"/>
|
||||
</LinearLayout>
|
||||
@@ -0,0 +1,9 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.tophold.trade.view.kview.KView
|
||||
android:id="@+id/fk_kv_kview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</FrameLayout>
|
||||
@@ -0,0 +1,9 @@
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<com.tophold.trade.view.kview.KView
|
||||
android:id="@+id/fk_kv_kview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"/>
|
||||
</FrameLayout>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="45dp"
|
||||
android:background="#d9cfcf">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/iafl_tv_znName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="黄金"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/iafl_tv_enName"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/iafl_tv_znName"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="GOLD"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="#ffffff"/>
|
||||
</RelativeLayout>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="45dp"
|
||||
android:background="#fff">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/iafl_tv_znName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:layout_marginTop="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:textSize="18sp"
|
||||
android:text="黄金"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/iafl_tv_enName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/iafl_tv_znName"
|
||||
android:layout_marginLeft="10dp"
|
||||
android:textSize="10sp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="GOLD"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/iafl_tv_part"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginRight="10dp"
|
||||
android:text="主区"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:background="#8b8989"/>
|
||||
</RelativeLayout>
|
||||
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 6.0 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="colorPrimary">#3F51B5</color>
|
||||
<color name="colorPrimaryDark">#303F9F</color>
|
||||
<color name="colorAccent">#FF4081</color>
|
||||
|
||||
<!--具体业务-->
|
||||
<color name="color_tb_indicator">#ef1e13</color>
|
||||
<color name="color_tb_selectedTxt">#ef1e13</color>
|
||||
<color name="color_tb_Txt">#8a8a8b</color>
|
||||
|
||||
<!--交易分析四个颜色-->
|
||||
<color name="trade_analyze_pie_1">#f5b5ff</color>
|
||||
<color name="trade_analyze_pie_2">#aaacff</color>
|
||||
<color name="trade_analyze_pie_3">#96e0ff</color>
|
||||
<color name="trade_analyze_pie_4">#ffcf97</color>
|
||||
|
||||
<!--seekbar-->
|
||||
<color name="dtsb_bgColor">#cecfce</color>
|
||||
<color name="dtsb_thumb1Color">#ed5f53</color>
|
||||
<color name="dtsb_thumb11Color">#f59e97</color>
|
||||
<color name="dtsb_thumb2Color">#63a65e</color>
|
||||
<color name="dtsb_thumb22Color">#9cfa95</color>
|
||||
</resources>
|
||||
@@ -0,0 +1,4 @@
|
||||
<resources>
|
||||
<string name="app_name">FinancialCustomerView</string>
|
||||
<string name="string_placeHold">--</string>
|
||||
</resources>
|
||||
@@ -0,0 +1,16 @@
|
||||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
<item name="colorAccent">@color/colorAccent</item>
|
||||
</style>
|
||||
<style name="AppTheme_Fullscreen" parent="Theme.AppCompat.DayNight.NoActionBar">
|
||||
|
||||
<item name="android:windowNoTitle">true</item>
|
||||
<item name="android:windowFullscreen">true</item>
|
||||
<item name="android:windowIsTranslucent">true</item>
|
||||
</style>
|
||||
</resources>
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.tophold.example;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Example local unit test, which will execute on the development machine (host).
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
public class ExampleUnitTest {
|
||||
@Test
|
||||
public void addition_isCorrect() throws Exception {
|
||||
assertEquals(4, 2 + 2);
|
||||
}
|
||||
}
|
||||