├── .gitignore ├── .idea ├── compiler.xml ├── copyright │ └── profiles_settings.xml ├── gradle.xml ├── misc.xml ├── modules.xml ├── runConfigurations.xml └── vcs.xml ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── yongxiang │ │ └── timerulers │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── yongxiang │ │ │ └── timerulers │ │ │ ├── ExampleApplication.java │ │ │ └── MainActivity.java │ └── res │ │ ├── layout │ │ └── activity_main.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── yongxiang │ └── timerulers │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle ├── timebar_scale.gif └── timerulerslib ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src └── main ├── AndroidManifest.xml ├── java └── timerulers │ └── yongxiang │ └── com │ └── timerulerslib │ └── views │ ├── DeviceUtil.java │ ├── RecordDataExistTimeSegment.java │ ├── TimebarTickCriterion.java │ └── TimebarView.java └── res └── values ├── attrs.xml └── strings.xml /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /.idea/compiler.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /.idea/copyright/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 19 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 46 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # TimeRulers 2 | 3 | 一个可以缩放的时间轴 类似萤石云的录像进度条 4 | 5 | ![](./timebar_scale.gif) 6 | 7 | Usage 8 | ----- 9 | 1.在xml布局中引入: 10 | ``` 11 | 19 | ``` 20 | 21 | - 目前支持的自定义属性: 22 | * `middleCursorColor` 时间尺中间刻度条颜色 23 | - `recordTextColor` 时间刻度文字颜色 24 | - `recordBackgroundColor` 含有录像背景颜色 25 | - `timebarColor` 含有时间尺边框及刻度条颜色 26 | 27 | 28 | - 刻度条移动监听 29 | ``` 30 | mTimebarView.setOnBarMoveListener(new TimebarView.OnBarMoveListener() { 31 | @Override 32 | public void onBarMove(long screenLeftTime, long screenRightTime, long currentTime) { 33 | if (currentTime == -1) { 34 | Toast.makeText(MainActivity.this, "当前时刻没有录像", Toast.LENGTH_SHORT).show(); 35 | } 36 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 37 | } 38 | 39 | @Override 40 | public void OnBarMoveFinish(long screenLeftTime, long screenRightTime, long currentTime) { 41 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 42 | } 43 | }); 44 | 45 | mTimebarView.setOnBarScaledListener(new TimebarView.OnBarScaledListener() { 46 | @Override 47 | public void onOnBarScaledMode(int mode) { 48 | Log.d(TAG, "onOnBarScaledMode()" + mode); 49 | } 50 | 51 | @Override 52 | public void onBarScaled(long screenLeftTime, long screenRightTime, long currentTime) { 53 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 54 | Log.d(TAG, "onBarScaled()"); 55 | } 56 | 57 | @Override 58 | public void onBarScaleFinish(long screenLeftTime, long screenRightTime, long currentTime) { 59 | Log.d(TAG, "onBarScaleFinish()"); 60 | } 61 | }); 62 | 63 | } 64 | ``` 65 | 66 | - 刻度条缩放监听 67 | ``` 68 | mTimebarView.setOnBarScaledListener(new TimebarView.OnBarScaledListener() { 69 | @Override 70 | public void onOnBarScaledMode(int mode) { 71 | 返回缩放级别 72 | Log.d(TAG, "onOnBarScaledMode()" + mode); 73 | } 74 | 75 | @Override 76 | public void onBarScaled(long screenLeftTime, long screenRightTime, long currentTime) { 77 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 78 | Log.d(TAG, "onBarScaled()"); 79 | } 80 | 81 | @Override 82 | public void onBarScaleFinish(long screenLeftTime, long screenRightTime, long currentTime) { 83 | Log.d(TAG, "onBarScaleFinish()"); 84 | } 85 | }); 86 | 87 | } 88 | ``` 89 | 90 | - Download 91 | ``` 92 | dependencies { 93 | compile 'com.dingyongxiang.library:timebarview:1.9' 94 | } 95 | ``` 96 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | defaultConfig { 7 | applicationId "com.yongxiang.timerulers" 8 | minSdkVersion 19 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', { 25 | exclude group: 'com.android.support', module: 'support-annotations' 26 | }) 27 | compile 'com.android.support:appcompat-v7:25.3.1' 28 | compile 'com.android.support.constraint:constraint-layout:1.0.2' 29 | testCompile 'junit:junit:4.12' 30 | compile project(':timerulerslib') 31 | 32 | debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5.1' 33 | releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1' 34 | testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5.1' 35 | } 36 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in D:\Software\sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/yongxiang/timerulers/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.yongxiang.timerulers; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumentation test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.yongxiang.timerulers", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/yongxiang/timerulers/ExampleApplication.java: -------------------------------------------------------------------------------- 1 | package com.yongxiang.timerulers; 2 | 3 | import android.app.Application; 4 | 5 | import com.squareup.leakcanary.LeakCanary; 6 | 7 | /** 8 | * Created by dingyongxiang on 2017/6/6. 9 | */ 10 | 11 | public class ExampleApplication extends Application { 12 | @Override public void onCreate() { 13 | super.onCreate(); 14 | if (LeakCanary.isInAnalyzerProcess(this)) { 15 | // This process is dedicated to LeakCanary for heap analysis. 16 | // You should not init your app in this process. 17 | return; 18 | } 19 | LeakCanary.install(this); 20 | // Normal app init code... 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/yongxiang/timerulers/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.yongxiang.timerulers; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.ImageView; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import java.text.SimpleDateFormat; 13 | import java.util.ArrayList; 14 | import java.util.Calendar; 15 | import java.util.List; 16 | 17 | import timerulers.yongxiang.com.timerulerslib.views.RecordDataExistTimeSegment; 18 | import timerulers.yongxiang.com.timerulerslib.views.TimebarView; 19 | 20 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 21 | private String TAG = MainActivity.class.getSimpleName(); 22 | private TextView currentTimeTextView; 23 | private Button zoomInButton, zoomOutButton; 24 | private TimebarView mTimebarView; 25 | 26 | private Button mDayBt; 27 | private Button mHourBt; 28 | private Button mMinuteBt; 29 | private int recordDays = 7; 30 | private long currentRealDateTime = System.currentTimeMillis(); 31 | private Calendar calendar; 32 | 33 | private static long ONE_MINUTE_IN_MS = 60 * 1000; 34 | private static long ONE_HOUR_IN_MS = 60 * ONE_MINUTE_IN_MS; 35 | private static long ONE_DAY_IN_MS = 24 * ONE_HOUR_IN_MS; 36 | 37 | private SimpleDateFormat zeroTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 38 | 39 | 40 | @Override 41 | protected void onCreate(Bundle savedInstanceState) { 42 | super.onCreate(savedInstanceState); 43 | setContentView(R.layout.activity_main); 44 | 45 | mTimebarView = (TimebarView) findViewById(R.id.my_timebar_view); 46 | currentTimeTextView = (TextView) findViewById(R.id.current_time_tv); 47 | zoomInButton = (Button) findViewById(R.id.timebar_zoom_in_btn); 48 | zoomOutButton = (Button) findViewById(R.id.timebar_zoom_out_btn); 49 | mDayBt = (Button) findViewById(R.id.day); 50 | mHourBt = (Button) findViewById(R.id.hour); 51 | mMinuteBt = (Button) findViewById(R.id.minute); 52 | 53 | zoomInButton.setOnClickListener(this); 54 | zoomOutButton.setOnClickListener(this); 55 | mDayBt.setOnClickListener(this); 56 | mHourBt.setOnClickListener(this); 57 | mMinuteBt.setOnClickListener(this); 58 | 59 | calendar = Calendar.getInstance(); 60 | calendar.set(Calendar.HOUR_OF_DAY, 0); 61 | calendar.set(Calendar.MINUTE, 0); 62 | calendar.set(Calendar.SECOND, 0); 63 | //long timebarLeftEndPointTime = currentRealDateTime - 7 * 24 * 3600 * 1000; 64 | long timebarLeftEndPointTime = calendar.getTimeInMillis(); 65 | 66 | System.out.println("calendar:" + calendar.getTime() + " currentRealDateTime:" + currentRealDateTime); 67 | calendar = Calendar.getInstance(); 68 | calendar.set(Calendar.HOUR_OF_DAY, 0); 69 | calendar.set(Calendar.MINUTE, 0); 70 | calendar.set(Calendar.SECOND, 0); 71 | calendar.add(Calendar.DAY_OF_MONTH, 1); 72 | long timebarRightEndPointTime = calendar.getTimeInMillis(); 73 | //long timebarRightEndPointTime = currentRealDateTime + 3 * 3600 * 1000; 74 | 75 | mTimebarView.initTimebarLengthAndPosition(timebarLeftEndPointTime, 76 | timebarRightEndPointTime - 1000, currentRealDateTime); 77 | 78 | final List recordDataList = new ArrayList<>(); 79 | recordDataList.add(new RecordDataExistTimeSegment(timebarLeftEndPointTime - ONE_HOUR_IN_MS * 1, timebarLeftEndPointTime + ONE_HOUR_IN_MS * 3)); 80 | recordDataList.add(new RecordDataExistTimeSegment(timebarLeftEndPointTime + ONE_HOUR_IN_MS * 4, timebarLeftEndPointTime + ONE_HOUR_IN_MS * 8)); 81 | recordDataList.add(new RecordDataExistTimeSegment(timebarLeftEndPointTime + ONE_HOUR_IN_MS * 12, timebarLeftEndPointTime + ONE_HOUR_IN_MS * 19)); 82 | recordDataList.add(new RecordDataExistTimeSegment(timebarLeftEndPointTime + ONE_HOUR_IN_MS * 20, timebarRightEndPointTime)); 83 | 84 | mTimebarView.setRecordDataExistTimeClipsList(recordDataList); 85 | 86 | mTimebarView.openMove(); 87 | mTimebarView.checkVideo(true); 88 | 89 | 90 | mTimebarView.setOnBarMoveListener(new TimebarView.OnBarMoveListener() { 91 | @Override 92 | public void onBarMove(long screenLeftTime, long screenRightTime, long currentTime) { 93 | if (currentTime == -1) { 94 | Toast.makeText(MainActivity.this, "当前时刻没有录像", Toast.LENGTH_SHORT).show(); 95 | } 96 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 97 | } 98 | 99 | @Override 100 | public void OnBarMoveFinish(long screenLeftTime, long screenRightTime, long currentTime) { 101 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 102 | } 103 | }); 104 | 105 | mTimebarView.setOnBarScaledListener(new TimebarView.OnBarScaledListener() { 106 | @Override 107 | public void onOnBarScaledMode(int mode) { 108 | Log.d(TAG, "onOnBarScaledMode()" + mode); 109 | } 110 | 111 | @Override 112 | public void onBarScaled(long screenLeftTime, long screenRightTime, long currentTime) { 113 | currentTimeTextView.setText(zeroTimeFormat.format(currentTime)); 114 | Log.d(TAG, "onBarScaled()"); 115 | } 116 | 117 | @Override 118 | public void onBarScaleFinish(long screenLeftTime, long screenRightTime, long currentTime) { 119 | Log.d(TAG, "onBarScaleFinish()"); 120 | } 121 | }); 122 | 123 | } 124 | 125 | @Override 126 | protected void onResume() { 127 | super.onResume(); 128 | } 129 | 130 | 131 | @Override 132 | public void onClick(View v) { 133 | switch (v.getId()) { 134 | case R.id.timebar_zoom_in_btn: 135 | mTimebarView.scaleByPressingButton(true); 136 | break; 137 | case R.id.timebar_zoom_out_btn: 138 | mTimebarView.scaleByPressingButton(false); 139 | break; 140 | case R.id.day: 141 | mTimebarView.setMode(3); 142 | break; 143 | case R.id.hour: 144 | mTimebarView.setMode(2); 145 | break; 146 | case R.id.minute: 147 | mTimebarView.setMode(1); 148 | break; 149 | default: 150 | break; 151 | } 152 | } 153 | 154 | @Override 155 | protected void onDestroy() { 156 | super.onDestroy(); 157 | mTimebarView.recycle(); 158 | } 159 | } 160 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 15 | 16 |