diff --git a/twidere/src/main/java/org/mariotaku/twidere/activity/support/MediaViewerActivity.java b/twidere/src/main/java/org/mariotaku/twidere/activity/support/MediaViewerActivity.java index 305e77cc0..c186ac3ef 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/activity/support/MediaViewerActivity.java +++ b/twidere/src/main/java/org/mariotaku/twidere/activity/support/MediaViewerActivity.java @@ -28,6 +28,7 @@ import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentTransaction; @@ -39,6 +40,7 @@ import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.support.v7.app.ActionBar; import android.support.v7.widget.ShareActionProvider; +import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -71,6 +73,7 @@ import org.mariotaku.twidere.model.ParcelableMedia; import org.mariotaku.twidere.model.ParcelableMedia.VideoInfo.Variant; import org.mariotaku.twidere.model.ParcelableStatus; import org.mariotaku.twidere.util.AsyncTaskUtils; +import org.mariotaku.twidere.util.KeyboardShortcutsHandler; import org.mariotaku.twidere.util.MenuUtils; import org.mariotaku.twidere.util.SaveFileTask; import org.mariotaku.twidere.util.ThemeUtils; @@ -86,19 +89,15 @@ import pl.droidsonroids.gif.GifTextureView; import pl.droidsonroids.gif.InputSource.FileSource; -public final class MediaViewerActivity extends ThemedAppCompatActivity implements Constants, OnPageChangeListener { +public final class MediaViewerActivity extends BaseAppCompatActivity implements Constants, OnPageChangeListener { private static final String EXTRA_LOOP = "loop"; - + private static boolean ANIMATED_GIF_SUPPORTED = GifSupportChecker.isSupported(); private ViewPager mViewPager; - private MediaPagerAdapter mAdapter; - private ActionBar mActionBar; + private MediaPagerAdapter mPagerAdapter; private View mMediaStatusContainer; private LinePageIndicator mIndicator; - - private static boolean ANIMATED_GIF_SUPPORTED = GifSupportChecker.isSupported(); - @Override public int getThemeColor() { return ThemeUtils.getUserAccentColor(this); @@ -109,10 +108,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement return ThemeUtils.getViewerThemeResource(this); } - public boolean hasStatus() { - return getIntent().hasExtra(EXTRA_STATUS); - } - @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -124,37 +119,16 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement return super.onOptionsItemSelected(item); } - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - - } - - @Override - public void onPageSelected(int position) { - setBarVisibility(true); - } - - @Override - public void onPageScrollStateChanged(int state) { - - } - - @Override - public void onContentChanged() { - super.onContentChanged(); - mViewPager = (ViewPager) findViewById(R.id.view_pager); - mIndicator = (LinePageIndicator) findViewById(R.id.pager_indicator); - mMediaStatusContainer = findViewById(R.id.media_status_container); - } - @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - mActionBar = getSupportActionBar(); - mActionBar.setDisplayHomeAsUpEnabled(true); + final ActionBar actionBar = getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(true); + } setContentView(R.layout.activity_media_viewer); - mAdapter = new MediaPagerAdapter(this); - mViewPager.setAdapter(mAdapter); + mPagerAdapter = new MediaPagerAdapter(this); + mViewPager.setAdapter(mPagerAdapter); mViewPager.setPageMargin(getResources().getDimensionPixelSize(R.dimen.element_spacing_normal)); mViewPager.setOnPageChangeListener(this); mIndicator.setSelectedColor(getCurrentThemeColor()); @@ -163,7 +137,7 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement final long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1); final ParcelableMedia[] media = Utils.newParcelableArray(intent.getParcelableArrayExtra(EXTRA_MEDIA), ParcelableMedia.CREATOR); final ParcelableMedia currentMedia = intent.getParcelableExtra(EXTRA_CURRENT_MEDIA); - mAdapter.setMedia(accountId, media); + mPagerAdapter.setMedia(accountId, media); mIndicator.notifyDataSetChanged(); final int currentIndex = ArrayUtils.indexOf(media, currentMedia); if (currentIndex != -1) { @@ -185,13 +159,71 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement } } + public boolean hasStatus() { + return getIntent().hasExtra(EXTRA_STATUS); + } + + @Override + public void onContentChanged() { + super.onContentChanged(); + mViewPager = (ViewPager) findViewById(R.id.view_pager); + mIndicator = (LinePageIndicator) findViewById(R.id.pager_indicator); + mMediaStatusContainer = findViewById(R.id.media_status_container); + } + + @Override + public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { + + } + + @Override + public void onPageSelected(int position) { + setBarVisibility(true); + } + + @Override + public void onPageScrollStateChanged(int state) { + + } + + @Override + public boolean handleKeyboardShortcutSingle(@NonNull KeyboardShortcutsHandler handler, int keyCode, @NonNull KeyEvent event) { + final String action = handler.getKeyAction(CONTEXT_TAG_NAVIGATION, keyCode, event); + if (action != null) { + switch (action) { + case ACTION_NAVIGATION_PREVIOUS_TAB: { + final int previous = mViewPager.getCurrentItem() - 1; + if (previous < 0) { + } else if (previous < mPagerAdapter.getCount()) { + mViewPager.setCurrentItem(previous, true); + } + return true; + } + case ACTION_NAVIGATION_NEXT_TAB: { + final int next = mViewPager.getCurrentItem() + 1; + if (next >= mPagerAdapter.getCount()) { + } else if (next >= 0) { + mViewPager.setCurrentItem(next, true); + } + return true; + } + case ACTION_NAVIGATION_BACK: { + onBackPressed(); + return true; + } + } + } + return super.handleKeyboardShortcutSingle(handler, keyCode, event); + } + private ParcelableStatus getStatus() { return getIntent().getParcelableExtra(EXTRA_STATUS); } private boolean isBarShowing() { - if (mActionBar == null) return false; - return mActionBar.isShowing(); + final ActionBar actionBar = getSupportActionBar(); + if (actionBar == null) return false; + return actionBar.isShowing(); } private boolean isMediaStatusEnabled() { @@ -199,11 +231,12 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement } private void setBarVisibility(boolean visible) { - if (mActionBar == null) return; + final ActionBar actionBar = getSupportActionBar(); + if (actionBar == null) return; if (visible) { - mActionBar.show(); + actionBar.show(); } else { - mActionBar.hide(); + actionBar.hide(); } mIndicator.setVisibility(visible ? View.VISIBLE : View.GONE); @@ -271,28 +304,10 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement invalidateOptionsMenu(); } - protected void setImageViewVisibility(int visible) { - mImageView.setVisibility(visible); - - } - - protected void setLoadProgress(float progress) { - mProgressBar.setProgress(progress); - } - - protected void setLoadProgressVisibility(int visibility) { - mProgressBar.setVisibility(visibility); - } - @Override public void onLoaderReset(final Loader loader) { } - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_media_page_image_compat, container, false); - } - @Override public void onDownloadError(final Throwable t) { mContentLength = 0; @@ -320,29 +335,22 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement setLoadProgress(downloaded / mContentLength); } + protected void setImageViewVisibility(int visible) { + mImageView.setVisibility(visible); + + } + @Override - public void onPrepareOptionsMenu(Menu menu) { - super.onPrepareOptionsMenu(menu); - final File file = mImageFile; - final boolean isLoading = getLoaderManager().hasRunningLoaders(); - final boolean hasImage = file != null && file.exists(); - MenuUtils.setMenuItemAvailability(menu, R.id.refresh, !hasImage && !isLoading); - MenuUtils.setMenuItemAvailability(menu, R.id.share, hasImage && !isLoading); - MenuUtils.setMenuItemAvailability(menu, R.id.save, hasImage && !isLoading); - if (!hasImage) return; - final MenuItem shareItem = menu.findItem(R.id.share); - final ShareActionProvider shareProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem); - final Intent intent = new Intent(Intent.ACTION_SEND); - final Uri fileUri = Uri.fromFile(file); - intent.setDataAndType(fileUri, Utils.getImageMimeType(file)); - intent.putExtra(Intent.EXTRA_STREAM, fileUri); - final MediaViewerActivity activity = (MediaViewerActivity) getActivity(); - if (activity.hasStatus()) { - final ParcelableStatus status = activity.getStatus(); - intent.putExtra(Intent.EXTRA_TEXT, Utils.getStatusShareText(activity, status)); - intent.putExtra(Intent.EXTRA_SUBJECT, Utils.getStatusShareSubject(activity, status)); - } - shareProvider.setShareIntent(intent); + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_media_page_image_compat, container, false); + } + + protected void setLoadProgress(float progress) { + mProgressBar.setProgress(progress); + } + + protected void setLoadProgressVisibility(int visibility) { + mProgressBar.setVisibility(visibility); } private ParcelableMedia getMedia() { @@ -372,11 +380,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement startActivity(intent); } - @Override - public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { - inflater.inflate(R.menu.menu_media_viewer_image_page, menu); - } - private void saveToGallery() { if (mSaveFileTask != null && mSaveFileTask.getStatus() == Status.RUNNING) return; final File file = mImageFile; @@ -386,6 +389,38 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement mSaveFileTask.execute(); } + @Override + public void onPrepareOptionsMenu(Menu menu) { + super.onPrepareOptionsMenu(menu); + final File file = mImageFile; + final boolean isLoading = getLoaderManager().hasRunningLoaders(); + final boolean hasImage = file != null && file.exists(); + MenuUtils.setMenuItemAvailability(menu, R.id.refresh, !hasImage && !isLoading); + MenuUtils.setMenuItemAvailability(menu, R.id.share, hasImage && !isLoading); + MenuUtils.setMenuItemAvailability(menu, R.id.save, hasImage && !isLoading); + if (!hasImage) return; + final MenuItem shareItem = menu.findItem(R.id.share); + final ShareActionProvider shareProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(shareItem); + final Intent intent = new Intent(Intent.ACTION_SEND); + final Uri fileUri = Uri.fromFile(file); + intent.setDataAndType(fileUri, Utils.getImageMimeType(file)); + intent.putExtra(Intent.EXTRA_STREAM, fileUri); + final MediaViewerActivity activity = (MediaViewerActivity) getActivity(); + if (activity.hasStatus()) { + final ParcelableStatus status = activity.getStatus(); + intent.putExtra(Intent.EXTRA_TEXT, Utils.getStatusShareText(activity, status)); + intent.putExtra(Intent.EXTRA_SUBJECT, Utils.getStatusShareSubject(activity, status)); + } + shareProvider.setShareIntent(intent); + } + + + @Override + public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_media_viewer_image_page, menu); + } + + @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { @@ -560,14 +595,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement return true; } - @Override - public void onBaseViewCreated(View view, Bundle savedInstanceState) { - super.onBaseViewCreated(view, savedInstanceState); - mVideoView = (TextureVideoView) view.findViewById(R.id.video_view); - mVideoViewProgress = (ProgressBar) view.findViewById(R.id.video_view_progress); - mProgressBar = (ProgressWheel) view.findViewById(R.id.load_progress); - } - @Override public void onPrepared(MediaPlayer mp) { if (getUserVisibleHint()) { @@ -591,6 +618,14 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement invalidateOptionsMenu(); } + @Override + public void onBaseViewCreated(View view, Bundle savedInstanceState) { + super.onBaseViewCreated(view, savedInstanceState); + mVideoView = (TextureVideoView) view.findViewById(R.id.video_view); + mVideoViewProgress = (ProgressBar) view.findViewById(R.id.video_view_progress); + mProgressBar = (ProgressWheel) view.findViewById(R.id.load_progress); + } + @Override public void onVideoLoadingComplete(String uri, VideoLoadingListener listener, File file) { mVideoView.setVideoURI(Uri.fromFile(file)); @@ -600,21 +635,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement invalidateOptionsMenu(); } - @Override - public void onActivityCreated(@Nullable Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - setHasOptionsMenu(true); - mVideoLoader = TwidereApplication.getInstance(getActivity()).getVideoLoader(); - mVideoProgressRunnable = new VideoPlayProgressRunnable(mVideoViewProgress.getHandler(), - mVideoViewProgress, mVideoView); - - mVideoView.setOnPreparedListener(this); - mVideoView.setOnErrorListener(this); - mVideoView.setOnCompletionListener(this); - - loadVideo(); - } - @Override public void onVideoLoadingFailed(String uri, VideoLoadingListener listener, Exception e) { mProgressBar.setVisibility(View.GONE); @@ -633,11 +653,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement mProgressBar.setProgress(current / (float) total); } - @Override - public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - return inflater.inflate(R.layout.fragment_media_page_video, container, false); - } - @Override public void onVideoLoadingStarted(String uri, VideoLoadingListener listener) { mProgressBar.setVisibility(View.VISIBLE); @@ -645,6 +660,29 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement invalidateOptionsMenu(); } + @Override + public void setUserVisibleHint(boolean isVisibleToUser) { + super.setUserVisibleHint(isVisibleToUser); + if (!isVisibleToUser && mVideoView != null && mVideoView.isPlaying()) { + mVideoView.pause(); + } + } + + @Override + public void onActivityCreated(@Nullable Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + setHasOptionsMenu(true); + mVideoLoader = TwidereApplication.getInstance(getActivity()).getVideoLoader(); + mVideoProgressRunnable = new VideoPlayProgressRunnable(mVideoViewProgress.getHandler(), + mVideoViewProgress, mVideoView); + + mVideoView.setOnPreparedListener(this); + mVideoView.setOnErrorListener(this); + mVideoView.setOnCompletionListener(this); + + loadVideo(); + } + private Pair getBestVideoUrlAndType(ParcelableMedia media) { if (media == null) return null; switch (media.type) { @@ -688,6 +726,36 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement mSaveFileTask = AsyncTaskUtils.executeTask(new SaveFileTask(getActivity(), file, mimeType, saveDir)); } + private static class VideoPlayProgressRunnable implements Runnable { + + private final Handler mHandler; + private final ProgressBar mProgressBar; + private final MediaController.MediaPlayerControl mMediaPlayerControl; + + VideoPlayProgressRunnable(Handler handler, ProgressBar progressBar, + MediaController.MediaPlayerControl mediaPlayerControl) { + mHandler = handler; + mProgressBar = progressBar; + mMediaPlayerControl = mediaPlayerControl; + mProgressBar.setMax(1000); + } + + @Override + public void run() { + final int duration = mMediaPlayerControl.getDuration(); + final int position = mMediaPlayerControl.getCurrentPosition(); + if (duration <= 0 || position < 0) return; + mProgressBar.setProgress(Math.round(1000 * position / (float) duration)); + mHandler.postDelayed(this, 16); + } + } + + @Override + public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { + return inflater.inflate(R.layout.fragment_media_page_video, container, false); + } + + @Override public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); @@ -714,30 +782,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement shareProvider.setShareIntent(intent); } - private static class VideoPlayProgressRunnable implements Runnable { - - private final Handler mHandler; - private final ProgressBar mProgressBar; - private final MediaController.MediaPlayerControl mMediaPlayerControl; - - VideoPlayProgressRunnable(Handler handler, ProgressBar progressBar, - MediaController.MediaPlayerControl mediaPlayerControl) { - mHandler = handler; - mProgressBar = progressBar; - mMediaPlayerControl = mediaPlayerControl; - mProgressBar.setMax(1000); - } - - @Override - public void run() { - final int duration = mMediaPlayerControl.getDuration(); - final int position = mMediaPlayerControl.getCurrentPosition(); - if (duration <= 0 || position < 0) return; - mProgressBar.setProgress(Math.round(1000 * position / (float) duration)); - mHandler.postDelayed(this, 16); - } - } - @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { @@ -776,14 +820,6 @@ public final class MediaViewerActivity extends ThemedAppCompatActivity implement super.onPause(); } - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - if (!isVisibleToUser && mVideoView != null && mVideoView.isPlaying()) { - mVideoView.pause(); - } - } - } } diff --git a/twidere/src/main/java/org/mariotaku/twidere/util/RecyclerViewNavigationHelper.java b/twidere/src/main/java/org/mariotaku/twidere/util/RecyclerViewNavigationHelper.java index 2be5b8680..1b954d4c1 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/util/RecyclerViewNavigationHelper.java +++ b/twidere/src/main/java/org/mariotaku/twidere/util/RecyclerViewNavigationHelper.java @@ -76,15 +76,16 @@ public class RecyclerViewNavigationHelper implements KeyboardShortcutCallback { final int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition(); final int lastVisibleItemPosition = layoutManager.findLastVisibleItemPosition(); final int itemCount = adapter.getItemCount(); + final boolean backupOutsideRange = positionBackup > lastVisibleItemPosition || positionBackup < firstVisibleItemPosition; if (focusedChild != null) { position = view.getChildLayoutPosition(focusedChild); } else if (firstVisibleItemPosition == 0) { position = -1; } else if (lastVisibleItemPosition == itemCount - 1) { position = itemCount; - } else if (direction > 0 && positionBackup < firstVisibleItemPosition) { + } else if (direction > 0 && backupOutsideRange) { position = firstVisibleItemPosition; - } else if (direction < 0 && positionBackup > lastVisibleItemPosition) { + } else if (direction < 0 && backupOutsideRange) { position = lastVisibleItemPosition; } else { position = positionBackup; diff --git a/twidere/src/main/java/org/mariotaku/twidere/view/BoundsImageView.java b/twidere/src/main/java/org/mariotaku/twidere/view/BoundsImageView.java index 11ae4fb71..5b83a06e0 100644 --- a/twidere/src/main/java/org/mariotaku/twidere/view/BoundsImageView.java +++ b/twidere/src/main/java/org/mariotaku/twidere/view/BoundsImageView.java @@ -19,10 +19,8 @@ package org.mariotaku.twidere.view; -import android.annotation.TargetApi; import android.content.Context; import android.graphics.Canvas; -import android.os.Build; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.widget.ImageView; @@ -43,11 +41,6 @@ public class BoundsImageView extends ImageView { super(context, attrs, defStyleAttr); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - public BoundsImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { - super(context, attrs, defStyleAttr, defStyleRes); - } - @Override protected void onDraw(@NonNull Canvas canvas) { setFrame(getLeft(), getTop(), getRight(), getBottom()); diff --git a/twidere/src/main/res/values/strings.xml b/twidere/src/main/res/values/strings.xml index 0717feb0f..723ced1a7 100644 --- a/twidere/src/main/res/values/strings.xml +++ b/twidere/src/main/res/values/strings.xml @@ -670,6 +670,8 @@ Members Subscriber Read from bottom + Jump to latest tweet after refreshing + Keep read position after refreshing Register Follows Belongs to diff --git a/twidere/src/main/res/xml/preferences_content.xml b/twidere/src/main/res/xml/preferences_content.xml index 08fc588af..a5c09766a 100644 --- a/twidere/src/main/res/xml/preferences_content.xml +++ b/twidere/src/main/res/xml/preferences_content.xml @@ -79,6 +79,8 @@