Media playlist
This commit is contained in:
parent
e92804ae34
commit
86e9572431
@ -15,8 +15,8 @@ android {
|
||||
applicationId "sushi.hardcore.droidfs"
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 29
|
||||
versionCode 11
|
||||
versionName "1.4.3"
|
||||
versionCode 12
|
||||
versionName "1.4.4"
|
||||
|
||||
ndk {
|
||||
abiFilters 'x86_64', 'armeabi-v7a', 'arm64-v8a'
|
||||
@ -54,10 +54,12 @@ dependencies {
|
||||
implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
|
||||
implementation "com.jaredrummler:cyanea:1.0.2"
|
||||
implementation "com.github.bumptech.glide:glide:4.11.0"
|
||||
implementation "com.google.android.exoplayer:exoplayer-core:2.11.7"
|
||||
implementation "com.google.android.exoplayer:exoplayer-ui:2.11.7"
|
||||
implementation "androidx.biometric:biometric:1.1.0"
|
||||
|
||||
def exoplayer_version = "2.13.2"
|
||||
implementation "com.google.android.exoplayer:exoplayer-core:$exoplayer_version"
|
||||
implementation "com.google.android.exoplayer:exoplayer-ui:$exoplayer_version"
|
||||
|
||||
def camerax_version = "1.1.0-alpha01"
|
||||
implementation "androidx.camera:camera-camera2:$camerax_version"
|
||||
implementation "androidx.camera:camera-lifecycle:$camerax_version"
|
||||
|
@ -21,7 +21,7 @@ class ConstValues {
|
||||
Pair("text", listOf("txt", "json", "conf", "log", "xml", "java", "kt", "py", "pl", "rb", "go", "c", "h", "cpp", "hpp", "sh", "bat", "js", "html", "css", "php", "yml", "yaml", "ini", "md"))
|
||||
)
|
||||
|
||||
private fun isExtensionType(extensionType: String, path: String): Boolean {
|
||||
fun isExtensionType(extensionType: String, path: String): Boolean {
|
||||
return fileExtensions[extensionType]?.contains(File(path).extension.toLowerCase(Locale.ROOT)) ?: false
|
||||
}
|
||||
|
||||
|
@ -112,12 +112,11 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
private fun startFileViewer(cls: Class<*>, filePath: String, sortOrder: String = ""){
|
||||
val intent = Intent(this, cls)
|
||||
intent.putExtra("path", filePath)
|
||||
intent.putExtra("sessionID", gocryptfsVolume.sessionID)
|
||||
if (sortOrder.isNotEmpty()){
|
||||
intent.putExtra("sortOrder", sortOrder)
|
||||
private fun startFileViewer(cls: Class<*>, filePath: String){
|
||||
val intent = Intent(this, cls).apply {
|
||||
putExtra("path", filePath)
|
||||
putExtra("sessionID", gocryptfsVolume.sessionID)
|
||||
putExtra("sortOrder", sortOrderValues[currentSortOrderIndex])
|
||||
}
|
||||
isStartingActivity = true
|
||||
startActivity(intent)
|
||||
@ -142,7 +141,7 @@ open class BaseExplorerActivity : BaseActivity() {
|
||||
setCurrentPath(PathUtils.getParentPath(currentDirectoryPath))
|
||||
}
|
||||
isImage(fullPath) -> {
|
||||
startFileViewer(ImageViewer::class.java, fullPath, sortOrderValues[currentSortOrderIndex])
|
||||
startFileViewer(ImageViewer::class.java, fullPath)
|
||||
}
|
||||
isVideo(fullPath) -> {
|
||||
startFileViewer(VideoPlayer::class.java, fullPath)
|
||||
|
@ -9,6 +9,22 @@ class AudioPlayer: MediaPlayer(){
|
||||
override fun viewFile() {
|
||||
setContentView(R.layout.activity_audio_player)
|
||||
super.viewFile()
|
||||
refreshFileName()
|
||||
}
|
||||
|
||||
override fun getFileType(): String {
|
||||
return "audio"
|
||||
}
|
||||
|
||||
override fun bindPlayer(player: SimpleExoPlayer) {
|
||||
audio_controller.player = player
|
||||
}
|
||||
|
||||
override fun onPlaylistIndexChanged() {
|
||||
refreshFileName()
|
||||
}
|
||||
|
||||
private fun refreshFileName() {
|
||||
val filename = File(filePath).name
|
||||
val pos = filename.lastIndexOf('.')
|
||||
music_title.text = if (pos != -1){
|
||||
@ -17,8 +33,4 @@ class AudioPlayer: MediaPlayer(){
|
||||
filename
|
||||
}
|
||||
}
|
||||
|
||||
override fun bindPlayer(player: SimpleExoPlayer) {
|
||||
audio_controller.player = player
|
||||
}
|
||||
}
|
@ -3,16 +3,23 @@ package sushi.hardcore.droidfs.file_viewers
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import sushi.hardcore.droidfs.BaseActivity
|
||||
import sushi.hardcore.droidfs.ConstValues
|
||||
import sushi.hardcore.droidfs.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.content_providers.RestrictedFileProvider
|
||||
import sushi.hardcore.droidfs.GocryptfsVolume
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
|
||||
abstract class FileViewerActivity: BaseActivity() {
|
||||
lateinit var gocryptfsVolume: GocryptfsVolume
|
||||
lateinit var filePath: String
|
||||
protected lateinit var gocryptfsVolume: GocryptfsVolume
|
||||
protected lateinit var filePath: String
|
||||
private var isFinishingIntentionally = false
|
||||
private var usf_keep_open = false
|
||||
private var wasMapped = false
|
||||
protected val mappedPlaylist = mutableListOf<ExplorerElement>()
|
||||
protected var currentPlaylistIndex = -1
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
filePath = intent.getStringExtra("path")!!
|
||||
@ -22,6 +29,7 @@ abstract class FileViewerActivity: BaseActivity() {
|
||||
hideSystemUi()
|
||||
viewFile()
|
||||
}
|
||||
|
||||
open fun hideSystemUi(){
|
||||
window.decorView.systemUiVisibility =
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN/* or
|
||||
@ -31,14 +39,18 @@ abstract class FileViewerActivity: BaseActivity() {
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION*/
|
||||
}
|
||||
|
||||
abstract fun getFileType(): String
|
||||
abstract fun viewFile()
|
||||
|
||||
override fun onUserInteraction() {
|
||||
super.onUserInteraction()
|
||||
if (window.decorView.systemUiVisibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0){
|
||||
hideSystemUi()
|
||||
}
|
||||
}
|
||||
fun loadWholeFile(path: String): ByteArray? {
|
||||
|
||||
protected fun loadWholeFile(path: String): ByteArray? {
|
||||
val fileSize = gocryptfsVolume.getSize(path)
|
||||
if (fileSize >= 0){
|
||||
try {
|
||||
@ -86,6 +98,48 @@ abstract class FileViewerActivity: BaseActivity() {
|
||||
return null
|
||||
}
|
||||
|
||||
protected fun createPlaylist() {
|
||||
if (!wasMapped){
|
||||
for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){
|
||||
if (e.isRegularFile) {
|
||||
if (ConstValues.isExtensionType(getFileType(), e.name) || filePath == e.fullPath) {
|
||||
mappedPlaylist.add(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
val sortOrder = intent.getStringExtra("sortOrder") ?: "name"
|
||||
ExplorerElement.sortBy(sortOrder, mappedPlaylist)
|
||||
//find current index
|
||||
for ((i, e) in mappedPlaylist.withIndex()){
|
||||
if (filePath == e.fullPath){
|
||||
currentPlaylistIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
wasMapped = true
|
||||
}
|
||||
}
|
||||
|
||||
protected fun playlistNext(forward: Boolean) {
|
||||
createPlaylist()
|
||||
currentPlaylistIndex = if (forward) {
|
||||
(currentPlaylistIndex+1)%mappedPlaylist.size
|
||||
} else {
|
||||
var x = (currentPlaylistIndex-1)%mappedPlaylist.size
|
||||
if (x < 0) {
|
||||
x += mappedPlaylist.size
|
||||
}
|
||||
x
|
||||
}
|
||||
filePath = mappedPlaylist[currentPlaylistIndex].fullPath
|
||||
}
|
||||
|
||||
protected fun refreshPlaylist() {
|
||||
mappedPlaylist.clear()
|
||||
wasMapped = false
|
||||
createPlaylist()
|
||||
}
|
||||
|
||||
protected fun goBackToExplorer() {
|
||||
isFinishingIntentionally = true
|
||||
finish()
|
||||
|
@ -1,7 +1,9 @@
|
||||
package sushi.hardcore.droidfs.file_viewers
|
||||
|
||||
import android.net.Uri
|
||||
import com.google.android.exoplayer2.upstream.*
|
||||
import com.google.android.exoplayer2.upstream.DataSource
|
||||
import com.google.android.exoplayer2.upstream.DataSpec
|
||||
import com.google.android.exoplayer2.upstream.TransferListener
|
||||
import sushi.hardcore.droidfs.ConstValues
|
||||
import sushi.hardcore.droidfs.GocryptfsVolume
|
||||
import kotlin.math.ceil
|
||||
@ -11,10 +13,8 @@ class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private
|
||||
private var handleID = -1
|
||||
private var fileSize: Long = -1
|
||||
private var fileOffset: Long = 0
|
||||
override fun open(dataSpec: DataSpec?): Long {
|
||||
dataSpec?.let {
|
||||
override fun open(dataSpec: DataSpec): Long {
|
||||
fileOffset = dataSpec.position
|
||||
}
|
||||
handleID = gocryptfsVolume.openReadMode(filePath)
|
||||
fileSize = gocryptfsVolume.getSize(filePath)
|
||||
return fileSize
|
||||
@ -28,7 +28,7 @@ class GocryptfsDataSource(private val gocryptfsVolume: GocryptfsVolume, private
|
||||
gocryptfsVolume.closeFile(handleID)
|
||||
}
|
||||
|
||||
override fun addTransferListener(transferListener: TransferListener?) {
|
||||
override fun addTransferListener(transferListener: TransferListener) {
|
||||
//too lazy to implement this
|
||||
}
|
||||
|
||||
|
@ -16,9 +16,6 @@ import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
|
||||
import kotlinx.android.synthetic.main.activity_image_viewer.*
|
||||
import sushi.hardcore.droidfs.ConstValues
|
||||
import sushi.hardcore.droidfs.R
|
||||
import sushi.hardcore.droidfs.explorers.ExplorerElement
|
||||
import sushi.hardcore.droidfs.util.MiscUtils
|
||||
import sushi.hardcore.droidfs.util.PathUtils
|
||||
import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
import sushi.hardcore.droidfs.widgets.ZoomableImageView
|
||||
import java.io.ByteArrayInputStream
|
||||
@ -36,11 +33,7 @@ class ImageViewer: FileViewerActivity() {
|
||||
private lateinit var glideImage: RequestBuilder<Drawable>
|
||||
private var x1 = 0F
|
||||
private var x2 = 0F
|
||||
private val mappedImages = mutableListOf<ExplorerElement>()
|
||||
private lateinit var sortOrder: String
|
||||
private var wasMapped = false
|
||||
private var slideshowActive = false
|
||||
private var currentMappedImageIndex = -1
|
||||
private var rotationAngle: Float = 0F
|
||||
private var rotatedBitmap: Bitmap? = null
|
||||
private val handler = Handler()
|
||||
@ -54,6 +47,11 @@ class ImageViewer: FileViewerActivity() {
|
||||
swipeImage(-1F, true)
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFileType(): String {
|
||||
return "image"
|
||||
}
|
||||
|
||||
override fun viewFile() {
|
||||
setContentView(R.layout.activity_image_viewer)
|
||||
image_viewer.setOnInteractionListener(object : ZoomableImageView.OnInteractionListener {
|
||||
@ -106,31 +104,7 @@ class ImageViewer: FileViewerActivity() {
|
||||
}
|
||||
|
||||
private fun swipeImage(deltaX: Float, slideshowSwipe: Boolean = false){
|
||||
if (!wasMapped){
|
||||
for (e in gocryptfsVolume.recursiveMapFiles(PathUtils.getParentPath(filePath))){
|
||||
if (e.isRegularFile && ConstValues.isImage(e.name)){
|
||||
mappedImages.add(e)
|
||||
}
|
||||
}
|
||||
sortOrder = intent.getStringExtra("sortOrder") ?: "name"
|
||||
ExplorerElement.sortBy(sortOrder, mappedImages)
|
||||
for ((i, e) in mappedImages.withIndex()){
|
||||
if (filePath == e.fullPath){
|
||||
currentMappedImageIndex = i
|
||||
break
|
||||
}
|
||||
}
|
||||
wasMapped = true
|
||||
}
|
||||
if (mappedImages.size == 0){ //can happen on deleting images
|
||||
goBackToExplorer()
|
||||
} else {
|
||||
currentMappedImageIndex = if (deltaX < 0){
|
||||
MiscUtils.incrementIndex(currentMappedImageIndex, mappedImages)
|
||||
} else {
|
||||
MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages)
|
||||
}
|
||||
filePath = mappedImages[currentMappedImageIndex].fullPath
|
||||
playlistNext(deltaX < 0)
|
||||
loadImage()
|
||||
if (slideshowActive){
|
||||
if (!slideshowSwipe) { //reset slideshow delay if user swipes
|
||||
@ -139,7 +113,6 @@ class ImageViewer: FileViewerActivity() {
|
||||
handler.postDelayed(slideshowNext, ConstValues.slideshow_delay)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onClickDelete(view: View) {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
@ -147,10 +120,13 @@ class ImageViewer: FileViewerActivity() {
|
||||
.setTitle(R.string.warning)
|
||||
.setPositiveButton(R.string.ok) { _, _ ->
|
||||
if (gocryptfsVolume.removeFile(filePath)){
|
||||
currentMappedImageIndex = MiscUtils.decrementIndex(currentMappedImageIndex, mappedImages)
|
||||
mappedImages.clear()
|
||||
wasMapped = false
|
||||
swipeImage(-1F)
|
||||
playlistNext(true)
|
||||
refreshPlaylist()
|
||||
if (mappedPlaylist.size == 0) { //deleted all images of the playlist
|
||||
goBackToExplorer()
|
||||
} else {
|
||||
loadImage()
|
||||
}
|
||||
} else {
|
||||
ColoredAlertDialogBuilder(this)
|
||||
.keepFullScreen()
|
||||
|
@ -1,18 +1,17 @@
|
||||
package sushi.hardcore.droidfs.file_viewers
|
||||
|
||||
import android.view.WindowManager
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.google.android.exoplayer2.ExoPlaybackException
|
||||
import com.google.android.exoplayer2.MediaItem
|
||||
import com.google.android.exoplayer2.Player
|
||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||
import com.google.android.exoplayer2.extractor.ExtractorsFactory
|
||||
import com.google.android.exoplayer2.extractor.flac.FlacExtractor
|
||||
import com.google.android.exoplayer2.extractor.mkv.MatroskaExtractor
|
||||
import com.google.android.exoplayer2.extractor.mp3.Mp3Extractor
|
||||
import com.google.android.exoplayer2.extractor.mp4.Mp4Extractor
|
||||
import com.google.android.exoplayer2.extractor.ogg.OggExtractor
|
||||
import com.google.android.exoplayer2.extractor.wav.WavExtractor
|
||||
import com.google.android.exoplayer2.source.LoopingMediaSource
|
||||
import com.google.android.exoplayer2.source.MediaSource
|
||||
import com.google.android.exoplayer2.source.ProgressiveMediaSource
|
||||
import sushi.hardcore.droidfs.ConstValues
|
||||
import sushi.hardcore.droidfs.R
|
||||
@ -20,46 +19,48 @@ import sushi.hardcore.droidfs.widgets.ColoredAlertDialogBuilder
|
||||
|
||||
abstract class MediaPlayer: FileViewerActivity() {
|
||||
private lateinit var player: SimpleExoPlayer
|
||||
private var currentWindow = 0
|
||||
private var playbackPosition: Long = 0
|
||||
private lateinit var errorDialog: AlertDialog
|
||||
|
||||
override fun viewFile() {
|
||||
errorDialog = ColoredAlertDialogBuilder(this)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.playing_failed)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer()}
|
||||
.create()
|
||||
hideSystemUi()
|
||||
initializePlayer()
|
||||
}
|
||||
|
||||
abstract fun bindPlayer(player: SimpleExoPlayer)
|
||||
protected open fun onPlaylistIndexChanged() {}
|
||||
|
||||
private fun initializePlayer(){
|
||||
player = SimpleExoPlayer.Builder(this).build()
|
||||
bindPlayer(player)
|
||||
private fun createMediaSource(filePath: String): MediaSource {
|
||||
val dataSourceFactory = GocryptfsDataSource.Factory(gocryptfsVolume, filePath)
|
||||
val mediaSource = ProgressiveMediaSource.Factory(dataSourceFactory, ExtractorsFactory {
|
||||
arrayOf(
|
||||
return ProgressiveMediaSource.Factory(dataSourceFactory, { arrayOf(
|
||||
MatroskaExtractor(),
|
||||
Mp4Extractor(),
|
||||
Mp3Extractor(),
|
||||
OggExtractor(),
|
||||
WavExtractor(),
|
||||
FlacExtractor()
|
||||
)
|
||||
}).createMediaSource(ConstValues.fakeUri)
|
||||
player.seekTo(currentWindow, playbackPosition)
|
||||
) }).createMediaSource(MediaItem.fromUri(ConstValues.fakeUri))
|
||||
}
|
||||
|
||||
private fun initializePlayer(){
|
||||
player = SimpleExoPlayer.Builder(this).build()
|
||||
bindPlayer(player)
|
||||
createPlaylist()
|
||||
for (e in mappedPlaylist) {
|
||||
player.addMediaSource(createMediaSource(e.fullPath))
|
||||
}
|
||||
player.repeatMode = Player.REPEAT_MODE_ALL
|
||||
player.seekToDefaultPosition(currentPlaylistIndex)
|
||||
player.playWhenReady = true
|
||||
player.addListener(object : Player.EventListener{
|
||||
override fun onPlayerError(error: ExoPlaybackException) {
|
||||
if (error.type == ExoPlaybackException.TYPE_SOURCE){
|
||||
errorDialog.show()
|
||||
ColoredAlertDialogBuilder(this@MediaPlayer)
|
||||
.setTitle(R.string.error)
|
||||
.setMessage(R.string.playing_failed)
|
||||
.setCancelable(false)
|
||||
.setPositiveButton(R.string.ok) { _, _ -> goBackToExplorer()}
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onIsPlayingChanged(isPlaying: Boolean) {
|
||||
if (isPlaying){
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
@ -67,20 +68,20 @@ abstract class MediaPlayer: FileViewerActivity() {
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||
}
|
||||
}
|
||||
override fun onPositionDiscontinuity(reason: Int) {
|
||||
if (player.currentWindowIndex != currentPlaylistIndex) {
|
||||
playlistNext(player.currentWindowIndex == (currentPlaylistIndex+1)%mappedPlaylist.size)
|
||||
onPlaylistIndexChanged()
|
||||
}
|
||||
}
|
||||
})
|
||||
player.prepare(LoopingMediaSource(mediaSource), false, false)
|
||||
}
|
||||
|
||||
private fun releasePlayer(){
|
||||
if (::player.isInitialized) {
|
||||
playbackPosition = player.currentPosition
|
||||
currentWindow = player.currentWindowIndex
|
||||
player.release()
|
||||
}
|
||||
player.prepare()
|
||||
}
|
||||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
releasePlayer()
|
||||
if (::player.isInitialized) {
|
||||
player.release()
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
package sushi.hardcore.droidfs.file_viewers
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.text.Editable
|
||||
import android.text.TextWatcher
|
||||
import android.view.Menu
|
||||
@ -24,6 +25,11 @@ class TextEditor: FileViewerActivity() {
|
||||
override fun hideSystemUi() {
|
||||
//don't hide system ui
|
||||
}
|
||||
|
||||
override fun getFileType(): String {
|
||||
return "text"
|
||||
}
|
||||
|
||||
override fun viewFile() {
|
||||
loadWholeFile(filePath)?.let {
|
||||
fileName = File(filePath).name
|
||||
@ -60,6 +66,7 @@ class TextEditor: FileViewerActivity() {
|
||||
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {
|
||||
if (!changedSinceLastSave){
|
||||
changedSinceLastSave = true
|
||||
@SuppressLint("SetTextI18n")
|
||||
titleText.text = "*$fileName"
|
||||
}
|
||||
}
|
||||
|
@ -13,4 +13,8 @@ class VideoPlayer: MediaPlayer() {
|
||||
override fun bindPlayer(player: SimpleExoPlayer) {
|
||||
video_player.player = player
|
||||
}
|
||||
|
||||
override fun getFileType(): String {
|
||||
return "video"
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package sushi.hardcore.droidfs.util
|
||||
|
||||
object MiscUtils {
|
||||
fun incrementIndex(index: Int, list: List<Any>): Int {
|
||||
var i = index+1
|
||||
if (i >= list.size){
|
||||
i = 0
|
||||
}
|
||||
return i
|
||||
}
|
||||
fun decrementIndex(index: Int, list: List<Any>): Int {
|
||||
var i = index-1
|
||||
if (i < 0){
|
||||
i = list.size-1
|
||||
}
|
||||
return i
|
||||
}
|
||||
}
|
@ -19,7 +19,6 @@
|
||||
android:id="@+id/audio_controller"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:controller_layout_id="@layout/exo_custom_playback_control"
|
||||
app:show_timeout="0"/>
|
||||
|
||||
</LinearLayout>
|
@ -2,15 +2,13 @@
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:gravity="center"
|
||||
android:background="@color/fullScreenBackgroundColor">
|
||||
|
||||
<com.google.android.exoplayer2.ui.SimpleExoPlayerView
|
||||
<com.google.android.exoplayer2.ui.PlayerView
|
||||
android:id="@+id/video_player"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_gravity="center"
|
||||
app:controller_layout_id="@layout/exo_custom_playback_control"/>
|
||||
android:layout_gravity="center"/>
|
||||
|
||||
</LinearLayout>
|
@ -1,74 +0,0 @@
|
||||
<?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="wrap_content"
|
||||
android:layout_gravity="bottom"
|
||||
android:layoutDirection="ltr"
|
||||
android:background="#CC000000"
|
||||
android:orientation="vertical">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingTop="4dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<ImageButton android:id="@id/exo_rew"
|
||||
style="@style/ExoMediaButton.Rewind"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_shuffle"
|
||||
style="@style/ExoMediaButton"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_repeat_toggle"
|
||||
style="@style/ExoMediaButton"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_play"
|
||||
style="@style/ExoMediaButton.Play"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_pause"
|
||||
style="@style/ExoMediaButton.Pause"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_ffwd"
|
||||
style="@style/ExoMediaButton.FastForward"/>
|
||||
|
||||
<ImageButton android:id="@id/exo_vr"
|
||||
style="@style/ExoMediaButton.VR"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView android:id="@id/exo_position"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:includeFontPadding="false"
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
<View android:id="@id/exo_progress_placeholder"
|
||||
android:layout_width="0dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_height="26dp"/>
|
||||
|
||||
<TextView android:id="@id/exo_duration"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold"
|
||||
android:paddingLeft="4dp"
|
||||
android:paddingRight="4dp"
|
||||
android:includeFontPadding="false"
|
||||
android:textColor="#FFBEBEBE"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
Loading…
Reference in New Issue
Block a user