From 7b2229f9a55a7b45c8dce95d7183c3f354bcff68 Mon Sep 17 00:00:00 2001 From: Mariotaku Lee Date: Tue, 18 Apr 2017 00:10:29 +0800 Subject: [PATCH] improved media viewer --- .../v7/app/WindowDecorActionBarAccessor.kt | 4 +- .../twidere/activity/MediaViewerActivity.kt | 53 +++++++++++++------ .../activity/iface/IControlBarActivity.kt | 7 ++- .../twidere/extension/ViewExtensions.kt | 8 +++ .../fragment/media/ExoPlayerPageFragment.kt | 28 ++++++++++ .../fragment/media/ImagePageFragment.kt | 5 ++ ...yout_media_viewer_video_controller_exo.xml | 1 + 7 files changed, 88 insertions(+), 18 deletions(-) diff --git a/twidere/src/main/kotlin/android/support/v7/app/WindowDecorActionBarAccessor.kt b/twidere/src/main/kotlin/android/support/v7/app/WindowDecorActionBarAccessor.kt index bd460e67f..1e04b3577 100644 --- a/twidere/src/main/kotlin/android/support/v7/app/WindowDecorActionBarAccessor.kt +++ b/twidere/src/main/kotlin/android/support/v7/app/WindowDecorActionBarAccessor.kt @@ -1,5 +1,7 @@ package android.support.v7.app import android.support.v7.widget.ActionBarContainer +import android.support.v7.widget.DecorToolbar -val WindowDecorActionBar.containerView: ActionBarContainer get() = mContainerView \ No newline at end of file +val WindowDecorActionBar.containerView: ActionBarContainer get() = mContainerView +val WindowDecorActionBar.decorToolbar: DecorToolbar get() = mDecorToolbar \ No newline at end of file diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MediaViewerActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MediaViewerActivity.kt index cbba6d74e..42ddbc30e 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MediaViewerActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/MediaViewerActivity.kt @@ -26,6 +26,7 @@ import android.os.Build import android.os.Bundle import android.os.Environment import android.os.Parcelable +import android.support.annotation.RequiresApi import android.support.v4.app.DialogFragment import android.support.v4.app.Fragment import android.support.v4.content.ContextCompat @@ -33,14 +34,16 @@ import android.support.v4.graphics.ColorUtils import android.support.v4.view.ViewPager import android.support.v4.widget.ViewDragHelper import android.support.v7.app.WindowDecorActionBar -import android.support.v7.app.containerView +import android.support.v7.app.decorToolbar import android.view.Menu import android.view.MenuItem +import android.view.View import android.view.WindowManager import android.widget.Toast import kotlinx.android.synthetic.main.activity_media_viewer.* import org.mariotaku.chameleon.Chameleon import org.mariotaku.ktextension.checkAllSelfPermissionsGranted +import org.mariotaku.ktextension.contains import org.mariotaku.ktextension.setItemAvailability import org.mariotaku.ktextension.toTypedArray import org.mariotaku.mediaviewer.library.* @@ -50,6 +53,8 @@ import org.mariotaku.twidere.TwidereConstants.* import org.mariotaku.twidere.activity.iface.IBaseActivity import org.mariotaku.twidere.activity.iface.IControlBarActivity.ControlBarShowHideHelper import org.mariotaku.twidere.annotation.CacheFileType +import org.mariotaku.twidere.extension.addSystemUiVisibility +import org.mariotaku.twidere.extension.removeSystemUiVisibility import org.mariotaku.twidere.fragment.PermissionRequestDialog import org.mariotaku.twidere.fragment.ProgressDialogFragment import org.mariotaku.twidere.fragment.iface.IBaseFragment @@ -95,6 +100,14 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos intent.getParcelableArrayExtra(EXTRA_MEDIA)?.toTypedArray(ParcelableMedia.CREATOR).orEmpty() } + private val currentFragment: MediaViewerFragment? get() { + val viewPager = findViewPager() + val adapter = viewPager.adapter + val currentItem = viewPager.currentItem + if (currentItem < 0 || currentItem >= adapter.count) return null + return adapter.instantiateItem(viewPager, currentItem) as? MediaViewerFragment + } + override val shouldApplyWindowBackground: Boolean = false override val controlBarHeight: Int @@ -114,7 +127,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos val actionBar = supportActionBar if (actionBar != null && !hideOffsetNotSupported) { if (actionBar is WindowDecorActionBar) { - val toolbar = actionBar.containerView + val toolbar = actionBar.decorToolbar.viewGroup toolbar.alpha = offset } try { @@ -157,7 +170,6 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos } } - override fun onContentChanged() { super.onContentChanged() mediaViewerHelper.onContentChanged() @@ -171,11 +183,7 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos override fun onPrepareOptionsMenu(menu: Menu): Boolean { super.onPrepareOptionsMenu(menu) - val viewPager = findViewPager() - val adapter = viewPager.adapter - val currentItem = viewPager.currentItem - if (currentItem < 0 || currentItem >= adapter.count) return false - val obj = adapter.instantiateItem(viewPager, currentItem) as? MediaViewerFragment ?: return false + val obj = currentFragment ?: return false if (obj.isDetached || obj.host == null) return false val running = obj.isMediaLoading val downloaded = obj.isMediaLoaded @@ -277,12 +285,23 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos } override fun isBarShowing(): Boolean { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + return FLAG_SYSTEM_UI_HIDE_BARS !in window.decorView.systemUiVisibility + } return controlBarOffset >= 1 } override fun setBarVisibility(visible: Boolean) { if (isBarShowing == visible) return - setControlBarVisibleAnimate(visible) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { + if (visible) { + window.decorView.removeSystemUiVisibility(FLAG_SYSTEM_UI_HIDE_BARS) + } else { + window.decorView.addSystemUiVisibility(FLAG_SYSTEM_UI_HIDE_BARS) + } + } else { + setControlBarVisibleAnimate(visible) + } } override fun getDownloader(): MediaDownloader { @@ -361,17 +380,18 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos override fun onSwipeStateChanged(state: Int) { supportActionBar?.let { + val barShowing = controlBarOffset >= 1 if (state == ViewDragHelper.STATE_IDLE) { - if (wasBarShowing == 1 && !isBarShowing) { - setBarVisibility(true) + if (wasBarShowing == 1 && !barShowing) { + setControlBarVisibleAnimate(true) } wasBarShowing = 0 } else { if (wasBarShowing == 0) { - wasBarShowing = if (isBarShowing) 1 else -1 + wasBarShowing = if (barShowing) 1 else -1 } - if (isBarShowing) { - setBarVisibility(false) + if (barShowing) { + setControlBarVisibleAnimate(false) } } } @@ -381,7 +401,6 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos controlBarShowHideHelper.setControlBarVisibleAnimate(visible, listener) } - override fun onFitSystemWindows(insets: Rect) { super.onFitSystemWindows(insets) val adapter = viewPager.adapter @@ -531,6 +550,10 @@ class MediaViewerActivity : BaseActivity(), IMediaViewerActivity, MediaSwipeClos private val REQUEST_SHARE_MEDIA = 201 private val REQUEST_PERMISSION_SAVE_MEDIA = 202 private val REQUEST_PERMISSION_SHARE_MEDIA = 203 + + @RequiresApi(Build.VERSION_CODES.JELLY_BEAN) + const val FLAG_SYSTEM_UI_HIDE_BARS = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or + View.SYSTEM_UI_FLAG_FULLSCREEN } } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/iface/IControlBarActivity.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/iface/IControlBarActivity.kt index cc99fe134..0baafbb6c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/activity/iface/IControlBarActivity.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/activity/iface/IControlBarActivity.kt @@ -49,7 +49,8 @@ interface IControlBarActivity { } interface ControlBarAnimationListener { - fun onControlBarVisibleAnimationFinish(visible: Boolean) + fun onControlBarVisibleAnimationStart(visible: Boolean) {} + fun onControlBarVisibleAnimationFinish(visible: Boolean) {} } fun setControlBarVisibleAnimate(visible: Boolean, listener: ControlBarAnimationListener? = null) { @@ -71,7 +72,9 @@ interface IControlBarActivity { } animator.interpolator = DecelerateInterpolator() animator.addListener(object : AnimatorListener { - override fun onAnimationStart(animation: Animator) {} + override fun onAnimationStart(animation: Animator) { + listener?.onControlBarVisibleAnimationStart(visible) + } override fun onAnimationEnd(animation: Animator) { controlAnimationDirection = 0 diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt index 6c1117c6a..936c5938c 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/extension/ViewExtensions.kt @@ -62,6 +62,14 @@ fun View.getLocationInWindow(rect: Rect) { rect.set(tempLocation[0], tempLocation[1], tempLocation[0] + width, tempLocation[1] + height) } +fun View.addSystemUiVisibility(systemUiVisibility: Int) { + this.systemUiVisibility = this.systemUiVisibility or systemUiVisibility +} + +fun View.removeSystemUiVisibility(systemUiVisibility: Int) { + this.systemUiVisibility = this.systemUiVisibility and systemUiVisibility.inv() +} + private fun offsetToRoot(view: View, rect: Rect) { var parent = view.parent as? View while (parent != null) { diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ExoPlayerPageFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ExoPlayerPageFragment.kt index ba555cd11..9cae1177d 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ExoPlayerPageFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ExoPlayerPageFragment.kt @@ -29,6 +29,7 @@ import android.os.Build import android.os.Bundle import android.os.Handler import android.view.LayoutInflater +import android.view.MotionEvent import android.view.View import android.view.ViewGroup import com.google.android.exoplayer2.* @@ -47,9 +48,11 @@ import kotlinx.android.synthetic.main.layout_media_viewer_video_overlay.* import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response +import org.mariotaku.ktextension.contains import org.mariotaku.mediaviewer.library.MediaViewerFragment import org.mariotaku.mediaviewer.library.subsampleimageview.SubsampleImageViewerFragment import org.mariotaku.twidere.R +import org.mariotaku.twidere.activity.MediaViewerActivity import org.mariotaku.twidere.annotation.CacheFileType import org.mariotaku.twidere.constant.IntentConstants.EXTRA_POSITION import org.mariotaku.twidere.extension.model.authorizationHeader @@ -127,6 +130,8 @@ class ExoPlayerPageFragment : MediaViewerFragment(), IBaseFragment { playbackCompleted = playWhenReady @@ -170,6 +175,29 @@ class ExoPlayerPageFragment : MediaViewerFragment(), IBaseFragment + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) return@setOnSystemUiVisibilityChangeListener + val visible = MediaViewerActivity.FLAG_SYSTEM_UI_HIDE_BARS !in + activity.window.decorView.systemUiVisibility + if (visible) { + playerView.showController() + } else { + playerView.hideController() + } + } + playerView.setOnTouchListener { _, event -> + if (event.action != MotionEvent.ACTION_DOWN) return@setOnTouchListener false + val activity = activity as? MediaViewerActivity ?: return@setOnTouchListener false + val visible = !activity.isBarShowing + activity.setBarVisibility(visible) + if (visible) { + playerView.showController() + } else { + playerView.hideController() + } + return@setOnTouchListener true + } updateVolume() } diff --git a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ImagePageFragment.kt b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ImagePageFragment.kt index 9c2d0d12d..a6d64f989 100644 --- a/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ImagePageFragment.kt +++ b/twidere/src/main/kotlin/org/mariotaku/twidere/fragment/media/ImagePageFragment.kt @@ -31,6 +31,7 @@ import com.davemorrissey.labs.subscaleview.decoder.SkiaImageDecoder import org.mariotaku.mediaviewer.library.CacheDownloadLoader import org.mariotaku.mediaviewer.library.subsampleimageview.SubsampleImageViewerFragment import org.mariotaku.twidere.TwidereConstants.* +import org.mariotaku.twidere.activity.MediaViewerActivity import org.mariotaku.twidere.model.ParcelableMedia import org.mariotaku.twidere.model.UserKey import org.mariotaku.twidere.util.TwidereMathUtils @@ -94,6 +95,10 @@ class ImagePageFragment : SubsampleImageViewerFragment() { imageView.maxScale = resources.displayMetrics.density imageView.setBitmapDecoderClass(PreviewBitmapDecoder::class.java) imageView.setParallelLoadingEnabled(true) + imageView.setOnClickListener { + val activity = activity as? MediaViewerActivity ?: return@setOnClickListener + activity.toggleBar() + } } override fun getImageSource(data: CacheDownloadLoader.Result): ImageSource { diff --git a/twidere/src/main/res/layout/layout_media_viewer_video_controller_exo.xml b/twidere/src/main/res/layout/layout_media_viewer_video_controller_exo.xml index e3c964098..652a3597e 100644 --- a/twidere/src/main/res/layout/layout_media_viewer_video_controller_exo.xml +++ b/twidere/src/main/res/layout/layout_media_viewer_video_controller_exo.xml @@ -24,6 +24,7 @@ android:layout_width="match_parent" android:layout_gravity="bottom" android:layout_height="?actionBarSize" + android:background="@drawable/bg_viewer_actionbar" android:clickable="true">