Skip to content

Commit

Permalink
Demo app for timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
alexeyvasilyev committed Jun 27, 2020
1 parent 98e20fb commit 31aa7d6
Show file tree
Hide file tree
Showing 23 changed files with 703 additions and 0 deletions.
120 changes: 120 additions & 0 deletions app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Created by https://www.gitignore.io/api/android,java,intellij

### Android ###
# Built application files
*.apk
*.ap_

# Files for the Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

xactmobile/class_files.txt
xactmobile/mapping.txt
xactmobile/seeds.txt

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

### Android Patch ###
gen-external-apklibs


### Java ###
*.class

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
#*.jar
*.war
*.ear

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*


### Intellij ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
.idea/workspace.xml
.idea/tasks.xml
.idea/dictionaries

# Sensitive or high-churn files:
.idea/dataSources.ids
.idea/dataSources.xml
.idea/sqlDataSources.xml
.idea/dynamic.xml
.idea/uiDesigner.xml

# Gradle:
.idea/gradle.xml
.idea/libraries

# Mongo Explorer plugin:
.idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties

xactmobile/.DS_Store~64be78fe3602626c61b52bcbfd09e09a6107b50a
xactmobile/.DS_Store~HEAD
oslab-viewpager/._.DS_Store
oslab-viewpager/src/main/.DS_Store
oslab-viewpager/src/main/._.DS_Store
oslab-viewpager/src/main/res/.DS_Store
oslab-viewpager/src/main/res/._.DS_Store
oslab-viewpager/.gitignore
oslab-materialdesign/.DS_Store
oslab-materialdesign/._.DS_Store
oslab-materialdesign/src/.DS_Store
oslab-materialdesign/src/._.DS_Store
oslab-materialdesign/src/main/.DS_Store
oslab-materialdesign/src/main/._.DS_Store
oslab-materialdesign/src/main/res/.DS_Store
oslab-materialdesign/src/main/res/._.DS_Store
54 changes: 54 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
apply from: '../constants.gradle'
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
compileSdkVersion 30
buildToolsVersion "30.0.0"

defaultConfig {
applicationId "com.alexvas.timeline.demo"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}

// To inline the bytecode built with JVM target 1.8 into
// bytecode that is being built with JVM target 1.6. (e.g. navArgs)


compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = "1.8"
}

}

dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "androidx.appcompat:appcompat:${androidXAppcompatVersion}"
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'com.google.android.material:material:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
implementation 'androidx.navigation:navigation-fragment:2.3.0'
implementation 'androidx.navigation:navigation-ui:2.3.0'
implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.0'
implementation 'androidx.navigation:navigation-ui-ktx:2.3.0'
implementation project(':library-timeline')
}
21 changes: 21 additions & 0 deletions app/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
23 changes: 23 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.alexvas.timeline.demo">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>
26 changes: 26 additions & 0 deletions app/src/main/java/com/alexvas/timeline/demo/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.alexvas.timeline.demo

import android.os.Bundle
import com.google.android.material.bottomnavigation.BottomNavigationView
import androidx.appcompat.app.AppCompatActivity
import androidx.navigation.findNavController
import androidx.navigation.ui.AppBarConfiguration
import androidx.navigation.ui.setupActionBarWithNavController
import androidx.navigation.ui.setupWithNavController

class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)

val navController = findNavController(R.id.nav_host_fragment)
// Passing each menu ID as a set of Ids because each
// menu should be considered as top level destinations.
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_timeline))
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
}
131 changes: 131 additions & 0 deletions app/src/main/java/com/alexvas/timeline/demo/ui/TimelineFragment.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package com.alexvas.timeline.demo.ui

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider
import com.alexvas.timeline.demo.R
import com.alexvas.widget.TimelineView
import com.alexvas.widget.TimelineView.TimeRecord

class TimelineFragment : Fragment() {

private val TAG: String = TimelineFragment::class.java.simpleName
private val DEBUG = true

private lateinit var timelineView: TimelineView
private lateinit var timelineViewModel: TimelineViewModel
private val recordsBackgroundEvents: ArrayList<TimeRecord> = ArrayList()
private val recordsMajor1Events: ArrayList<TimeRecord> = ArrayList()
private val recordsMajor2Events: ArrayList<TimeRecord> = ArrayList()

override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
timelineViewModel =
ViewModelProvider(this).get(TimelineViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_timeline, container, false)
timelineView = root.findViewById(R.id.timeline)
timelineView.setOnTimelineListener(object:TimelineView.OnTimelineListener {
override fun onTimeSelecting() {
}

override fun onTimeSelected(timestampMsec: Long, record: TimeRecord?) {
}

override fun onRequestMoreMajor1Data() {
}

override fun onRequestMoreMajor2Data() {
}

override fun onRequestMoreBackgroundData() {
}
})
return root
}

override fun onStart() {
if (DEBUG) Log.v(TAG, "onStart()")
super.onStart()
timelineViewModel.loadParams(context)
loadFirstValues()
updateTimeline()
gotoLastMajor1Record()
}

override fun onStop() {
if (DEBUG) Log.v(TAG, "onStop()")
super.onStop()
timelineViewModel.saveParams(context)
}

class EventRecord(videoOffset: Int)

private fun loadFirstValues() {
if (DEBUG) Log.v(TAG, "loadFirstValues()")
val time = System.currentTimeMillis()
recordsMajor1Events.clear()
recordsMajor1Events.add(TimeRecord(time - 5000, 1000, EventRecord(0)))
recordsMajor1Events.add(TimeRecord(time - 30000, 20000, EventRecord(0)))
recordsMajor1Events.add(TimeRecord(time - 300000, 20000, EventRecord(0)))
recordsMajor1Events.add(TimeRecord(time - 1800000, 100000, EventRecord(0)))
recordsMajor1Events.add(TimeRecord(time - 3600000, 70000, EventRecord(0)))
recordsMajor1Events.add(TimeRecord(time - 360000000, 150000, EventRecord(0)))
recordsMajor1Events.add(TimeRecord(time - 500000000, 1500000, EventRecord(0)))

recordsMajor2Events.clear()
recordsMajor2Events.add(TimeRecord(time - 500, 500, EventRecord(0)))

recordsBackgroundEvents.clear()
recordsBackgroundEvents.add(TimeRecord(time - 500000, 500000, EventRecord(0)))
recordsBackgroundEvents.add(TimeRecord(time - 1000000, 250000, EventRecord(0)))
recordsBackgroundEvents.add(TimeRecord(time - 2500000, 1000000, EventRecord(0)))
}

private fun updateTimeline() {
if (DEBUG) Log.v(TAG, "updateTimeline()")
timelineView.setMajor1Records(recordsMajor1Events)
timelineView.setMajor2Records(recordsMajor2Events)
timelineView.setBackgroundRecords(recordsBackgroundEvents)
timelineView.invalidate()
}

private fun gotoLastMajor1Record() {
if (DEBUG) Log.v(TAG, "gotoLastMajor1Record()")
var records: java.util.ArrayList<TimeRecord> = timelineView.getMajor1Records()
// At least one event exists
if (records.size > 0) {
val record = records[0]
val timestamp: Long = getTimestampFromRecord(record)
onTimeSelected(timestamp, record)
timelineView.setCurrentWithAnimation(record.timestampMsec)
timelineView.invalidate()
} else {
// No events found. Show last video recording.
records = timelineView.getBackgroundRecords()
if (records.size > 0) {
val record = records[0]
// 30 sec before video finished.
val timestamp = record.timestampMsec + Math.max(record.durationMsec - 30000, 0)
onTimeSelected(timestamp, record)
timelineView.setCurrentWithAnimation(record.timestampMsec)
timelineView.invalidate()
}
}
}

private fun getTimestampFromRecord(record: TimeRecord): Long {
return record.timestampMsec
}

private fun onTimeSelected(timestamp: Long, record: TimeRecord) {
// TODO: Playback code goes here
}

}
Loading

0 comments on commit 31aa7d6

Please sign in to comment.