rewrite the way fullscreen images are loaded, for better quality, close #90, #84

This commit is contained in:
tibbi 2017-01-06 14:15:05 +01:00
parent 7d1e08ea19
commit 7b9503229f
9 changed files with 119 additions and 137 deletions

View file

@ -93,6 +93,7 @@
<activity <activity
android:name=".activities.PhotoVideoActivity" android:name=".activities.PhotoVideoActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:theme="@style/FullScreenTheme"/> android:theme="@style/FullScreenTheme"/>
<activity <activity

View file

@ -3,9 +3,11 @@ package com.simplemobiletools.gallery.activities
import android.os.Bundle import android.os.Bundle
class PhotoActivity : PhotoVideoActivity() { class PhotoActivity : PhotoVideoActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
PhotoVideoActivity.mIsVideo = false PhotoVideoActivity.mIsVideo = false
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
} }
override fun systemUiVisibilityChanged(visibility: Int) {
}
} }

View file

@ -1,12 +1,12 @@
package com.simplemobiletools.gallery.activities package com.simplemobiletools.gallery.activities
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore import android.provider.MediaStore
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
import android.view.View
import com.simplemobiletools.gallery.R import com.simplemobiletools.gallery.R
import com.simplemobiletools.gallery.extensions.* import com.simplemobiletools.gallery.extensions.*
import com.simplemobiletools.gallery.fragments.PhotoFragment import com.simplemobiletools.gallery.fragments.PhotoFragment
@ -16,7 +16,7 @@ import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.models.Medium import com.simplemobiletools.gallery.models.Medium
import java.io.File import java.io.File
open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentClickListener { open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentListener {
private var mMedium: Medium? = null private var mMedium: Medium? = null
private var mIsFullScreen = false private var mIsFullScreen = false
@ -46,6 +46,7 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentClic
} }
} }
showSystemUI()
val bundle = Bundle() val bundle = Bundle()
val file = File(mUri.toString()) val file = File(mUri.toString())
mMedium = Medium(file.name, mUri.toString(), mIsVideo, 0, 0, file.length()) mMedium = Medium(file.name, mUri.toString(), mIsVideo, 0, 0, file.length())
@ -80,11 +81,6 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentClic
} }
} }
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
mFragment.updateItem()
}
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.photo_video_menu, menu) menuInflater.inflate(R.menu.photo_video_menu, menu)
@ -113,4 +109,13 @@ open class PhotoVideoActivity : SimpleActivity(), ViewPagerFragment.FragmentClic
showSystemUI() showSystemUI()
} }
} }
override fun systemUiVisibilityChanged(visibility: Int) {
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
mIsFullScreen = false
showSystemUI()
} else {
mIsFullScreen = true
}
}
} }

View file

@ -2,7 +2,6 @@ package com.simplemobiletools.gallery.activities
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.res.Configuration
import android.database.Cursor import android.database.Cursor
import android.os.Bundle import android.os.Bundle
import android.provider.MediaStore import android.provider.MediaStore
@ -29,7 +28,7 @@ import kotlinx.android.synthetic.main.activity_medium.*
import java.io.File import java.io.File
import java.util.* import java.util.*
class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View.OnSystemUiVisibilityChangeListener, ViewPagerFragment.FragmentClickListener { class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, ViewPagerFragment.FragmentListener {
private var mMedia = ArrayList<Medium>() private var mMedia = ArrayList<Medium>()
private var mPath = "" private var mPath = ""
private var mDirectory = "" private var mDirectory = ""
@ -77,7 +76,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
mDirectory = File(mPath).parent mDirectory = File(mPath).parent
title = mPath.getFilenameFromPath() title = mPath.getFilenameFromPath()
window.decorView.setOnSystemUiVisibilityChangeListener(this)
reloadViewPager() reloadViewPager()
scanPath(mPath) {} scanPath(mPath) {}
} }
@ -114,12 +112,6 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
return true return true
} }
override fun onConfigurationChanged(newConfig: Configuration) {
super.onConfigurationChanged(newConfig)
val adapter = view_pager.adapter as MyPagerAdapter
adapter.updateItems(mPos)
}
private fun updatePagerItems() { private fun updatePagerItems() {
val pagerAdapter = MyPagerAdapter(this, supportFragmentManager, mMedia) val pagerAdapter = MyPagerAdapter(this, supportFragmentManager, mMedia)
view_pager.apply { view_pager.apply {
@ -260,6 +252,15 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
} }
} }
override fun systemUiVisibilityChanged(visibility: Int) {
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
mIsFullScreen = false
showSystemUI()
} else {
mIsFullScreen = true
}
}
private fun updateActionbarTitle() { private fun updateActionbarTitle() {
runOnUiThread { runOnUiThread {
title = mMedia[mPos].path.getFilenameFromPath() title = mMedia[mPos].path.getFilenameFromPath()
@ -286,20 +287,5 @@ class ViewPagerActivity : SimpleActivity(), ViewPager.OnPageChangeListener, View
} }
override fun onPageScrollStateChanged(state: Int) { override fun onPageScrollStateChanged(state: Int) {
if (state == ViewPager.SCROLL_STATE_DRAGGING) {
val adapter = view_pager.adapter as MyPagerAdapter
adapter.itemDragged(mPos)
}
}
override fun onSystemUiVisibilityChange(visibility: Int) {
view_pager.adapter?.apply {
if (visibility and View.SYSTEM_UI_FLAG_FULLSCREEN == 0) {
mIsFullScreen = false
showSystemUI()
}
(this as MyPagerAdapter).updateUiVisibility(mIsFullScreen, mPos)
}
} }
} }

View file

@ -5,7 +5,6 @@ import android.support.v4.app.Fragment
import android.support.v4.app.FragmentManager import android.support.v4.app.FragmentManager
import android.support.v4.app.FragmentStatePagerAdapter import android.support.v4.app.FragmentStatePagerAdapter
import android.support.v4.view.PagerAdapter import android.support.v4.view.PagerAdapter
import android.util.SparseArray
import com.simplemobiletools.gallery.activities.ViewPagerActivity import com.simplemobiletools.gallery.activities.ViewPagerActivity
import com.simplemobiletools.gallery.fragments.PhotoFragment import com.simplemobiletools.gallery.fragments.PhotoFragment
import com.simplemobiletools.gallery.fragments.VideoFragment import com.simplemobiletools.gallery.fragments.VideoFragment
@ -14,8 +13,6 @@ import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.models.Medium import com.simplemobiletools.gallery.models.Medium
class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val media: MutableList<Medium>) : FragmentStatePagerAdapter(fm) { class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val media: MutableList<Medium>) : FragmentStatePagerAdapter(fm) {
private val mFragments: SparseArray<ViewPagerFragment> = SparseArray<ViewPagerFragment>()
override fun getCount() = media.size override fun getCount() = media.size
override fun getItem(position: Int): Fragment { override fun getItem(position: Int): Fragment {
@ -30,25 +27,10 @@ class MyPagerAdapter(val activity: ViewPagerActivity, fm: FragmentManager, val m
fragment = PhotoFragment() fragment = PhotoFragment()
} }
mFragments.put(position, fragment)
fragment.arguments = bundle fragment.arguments = bundle
fragment.listener = activity fragment.listener = activity
return fragment return fragment
} }
override fun getItemPosition(item: Any?) = PagerAdapter.POSITION_NONE override fun getItemPosition(item: Any?) = PagerAdapter.POSITION_NONE
fun itemDragged(pos: Int) {
mFragments[pos]?.itemDragged()
}
fun updateUiVisibility(isFullscreen: Boolean, pos: Int) {
(-1..1).map { mFragments[pos + it] }
.forEach { it?.systemUiVisibilityChanged(isFullscreen) }
}
fun updateItems(pos: Int) {
(-1..1).map { mFragments[pos + it] }
.forEach { it?.updateItem() }
}
} }

View file

@ -1,12 +1,17 @@
package com.simplemobiletools.gallery.fragments package com.simplemobiletools.gallery.fragments
import android.content.res.Configuration
import android.graphics.Bitmap
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.davemorrissey.labs.subscaleview.ImageSource import com.davemorrissey.labs.subscaleview.ImageSource
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
import com.simplemobiletools.gallery.R import com.simplemobiletools.gallery.R
@ -15,38 +20,62 @@ import com.simplemobiletools.gallery.helpers.MEDIUM
import com.simplemobiletools.gallery.models.Medium import com.simplemobiletools.gallery.models.Medium
import kotlinx.android.synthetic.main.pager_photo_item.view.* import kotlinx.android.synthetic.main.pager_photo_item.view.*
class PhotoFragment : ViewPagerFragment(), View.OnClickListener { class PhotoFragment : ViewPagerFragment() {
lateinit var subsamplingView: SubsamplingScaleImageView
lateinit var medium: Medium lateinit var medium: Medium
lateinit var mView: View
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = inflater.inflate(R.layout.pager_photo_item, container, false) mView = inflater.inflate(R.layout.pager_photo_item, container, false)
medium = arguments.getSerializable(MEDIUM) as Medium medium = arguments.getSerializable(MEDIUM) as Medium
if (medium.path.startsWith("content://")) if (medium.path.startsWith("content://"))
medium.path = context.getRealPathFromURI(Uri.parse(medium.path)) ?: "" medium.path = context.getRealPathFromURI(Uri.parse(medium.path)) ?: ""
subsamplingView = view.photo_view loadImage(medium)
if (medium.isGif()) {
subsamplingView.visibility = View.GONE activity.window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
view.glide_view.apply { listener?.systemUiVisibilityChanged(visibility)
visibility = View.VISIBLE
Glide.with(context).load(medium.path).asGif().diskCacheStrategy(DiskCacheStrategy.NONE).into(this)
setOnClickListener(this@PhotoFragment)
} }
return mView
}
private fun loadImage(medium: Medium) {
val subsamplingView = mView.photo_view.apply { setOnClickListener({ photoClicked() }) }
val glideView = mView.glide_view.apply { setOnClickListener({ photoClicked() }) }
if (medium.isGif()) {
Glide.with(this)
.load(medium.path)
.asGif()
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(glideView)
} else { } else {
Glide.with(this)
.load(medium.path)
.asBitmap()
.format(if (medium.isPng()) DecodeFormat.PREFER_ARGB_8888 else DecodeFormat.PREFER_RGB_565)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.listener(object : RequestListener<String, Bitmap> {
override fun onException(e: Exception?, model: String?, target: Target<Bitmap>?, isFirstResource: Boolean): Boolean {
return false
}
override fun onResourceReady(resource: Bitmap?, model: String?, target: Target<Bitmap>?, isFromMemoryCache: Boolean, isFirstResource: Boolean): Boolean {
if (!medium.isPng()) {
subsamplingView.visibility = View.VISIBLE
subsamplingView.apply { subsamplingView.apply {
setDoubleTapZoomScale(1.2f) setDoubleTapZoomScale(1.2f)
orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF
setImage(ImageSource.uri(medium.path)) setImage(ImageSource.uri(medium.path))
maxScale = 4f orientation = SubsamplingScaleImageView.ORIENTATION_USE_EXIF
setMinimumTileDpi(100) maxScale = 5f
setOnClickListener(this@PhotoFragment)
setOnImageEventListener(object : SubsamplingScaleImageView.OnImageEventListener { setOnImageEventListener(object : SubsamplingScaleImageView.OnImageEventListener {
override fun onImageLoaded() { override fun onImageLoaded() {
} }
override fun onReady() { override fun onReady() {
glideView.visibility = View.GONE
subsamplingView.visibility = View.VISIBLE
} }
override fun onTileLoadError(p0: Exception?) { override fun onTileLoadError(p0: Exception?) {
@ -56,12 +85,6 @@ class PhotoFragment : ViewPagerFragment(), View.OnClickListener {
} }
override fun onImageLoadError(p0: Exception?) { override fun onImageLoadError(p0: Exception?) {
subsamplingView.visibility = View.GONE
view.glide_view.apply {
visibility = View.VISIBLE
Glide.with(context).load(medium.path).diskCacheStrategy(DiskCacheStrategy.NONE).into(this)
setOnClickListener(this@PhotoFragment)
}
} }
override fun onPreviewLoadError(p0: Exception?) { override fun onPreviewLoadError(p0: Exception?) {
@ -69,28 +92,18 @@ class PhotoFragment : ViewPagerFragment(), View.OnClickListener {
}) })
} }
} }
return false
return view }
}).into(glideView)
}
} }
override fun itemDragged() { override fun onConfigurationChanged(newConfig: Configuration?) {
} super.onConfigurationChanged(newConfig)
loadImage(medium)
override fun systemUiVisibilityChanged(toFullscreen: Boolean) {
}
override fun updateItem() {
subsamplingView.setImage(ImageSource.uri(medium.path))
}
override fun onClick(v: View) {
photoClicked()
} }
private fun photoClicked() { private fun photoClicked() {
if (listener == null)
listener = activity as ViewPagerFragment.FragmentClickListener
listener?.fragmentClicked() listener?.fragmentClicked()
} }
} }

View file

@ -5,6 +5,7 @@ import android.media.AudioManager
import android.media.MediaPlayer import android.media.MediaPlayer
import android.media.MediaPlayer.OnPreparedListener import android.media.MediaPlayer.OnPreparedListener
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Handler import android.os.Handler
import android.util.DisplayMetrics import android.util.DisplayMetrics
@ -61,6 +62,13 @@ class VideoFragment : ViewPagerFragment(), View.OnClickListener, SurfaceHolder.C
setupPlayer() setupPlayer()
mView.setOnClickListener(this) mView.setOnClickListener(this)
activity.window.decorView.setOnSystemUiVisibilityChangeListener { visibility ->
val fullscreen = visibility and View.SYSTEM_UI_FLAG_FULLSCREEN != 0
mIsFullscreen = fullscreen
checkFullscreen()
listener?.systemUiVisibilityChanged(visibility)
}
return mView return mView
} }
@ -85,21 +93,14 @@ class VideoFragment : ViewPagerFragment(), View.OnClickListener, SurfaceHolder.C
if (context != null && Config.newInstance(context).autoplayVideos) { if (context != null && Config.newInstance(context).autoplayVideos) {
playVideo() playVideo()
} }
} } else {
} if (mIsPlaying)
override fun itemDragged() {
pauseVideo() pauseVideo()
} }
override fun systemUiVisibilityChanged(toFullscreen: Boolean) {
if (mIsFullscreen != toFullscreen) {
mIsFullscreen = toFullscreen
checkFullscreen()
}
} }
override fun updateItem() { override fun onConfigurationChanged(newConfig: Configuration?) {
super.onConfigurationChanged(newConfig)
setVideoSize() setVideoSize()
initTimeHolder() initTimeHolder()
} }
@ -162,10 +163,6 @@ class VideoFragment : ViewPagerFragment(), View.OnClickListener, SurfaceHolder.C
else -> { else -> {
mIsFullscreen = !mIsFullscreen mIsFullscreen = !mIsFullscreen
checkFullscreen() checkFullscreen()
if (listener == null)
listener = activity as ViewPagerFragment.FragmentClickListener
listener?.fragmentClicked() listener?.fragmentClicked()
} }
} }
@ -302,7 +299,7 @@ class VideoFragment : ViewPagerFragment(), View.OnClickListener, SurfaceHolder.C
val screenWidth: Int val screenWidth: Int
val screenHeight: Int val screenHeight: Int
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
val realMetrics = DisplayMetrics() val realMetrics = DisplayMetrics()
display.getRealMetrics(realMetrics) display.getRealMetrics(realMetrics)
screenWidth = realMetrics.widthPixels screenWidth = realMetrics.widthPixels

View file

@ -3,15 +3,11 @@ package com.simplemobiletools.gallery.fragments
import android.support.v4.app.Fragment import android.support.v4.app.Fragment
abstract class ViewPagerFragment : Fragment() { abstract class ViewPagerFragment : Fragment() {
var listener: FragmentClickListener? = null var listener: FragmentListener? = null
abstract fun itemDragged() interface FragmentListener {
abstract fun systemUiVisibilityChanged(toFullscreen: Boolean)
abstract fun updateItem()
interface FragmentClickListener {
fun fragmentClicked() fun fragmentClicked()
fun systemUiVisibilityChanged(visibility: Int)
} }
} }

View file

@ -5,13 +5,13 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView <ImageView
android:id="@+id/photo_view" android:id="@+id/glide_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
<ImageView <com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView
android:id="@+id/glide_view" android:id="@+id/photo_view"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:visibility="gone"/> android:visibility="gone"/>