Improve reader options menu. Allow to select default viewer per manga. Allow to lock screen rotation. Working on more options.

This commit is contained in:
inorichi 2015-11-19 18:56:46 +01:00
parent 13e1227fc5
commit 5e2269df14
40 changed files with 254 additions and 60 deletions

View file

@ -40,6 +40,19 @@ public class PreferencesHelper {
return prefs.getBoolean(getKey(R.string.pref_hide_status_bar_key), true);
}
public boolean isOrientationLocked() {
return prefs.getBoolean(getKey(R.string.pref_lock_orientation_key), true);
}
public void setOrientationLocked(boolean lock) {
prefs.edit().putBoolean(getKey(R.string.pref_lock_orientation_key), lock).apply();
}
public Observable<Boolean> isOrientationLockedObservable() {
return rxPrefs.getBoolean(getKey(R.string.pref_lock_orientation_key), true)
.asObservable();
}
public int getDefaultViewer() {
return Integer.parseInt(prefs.getString(getKey(R.string.pref_default_viewer_key), "1"));
}

View file

@ -4,9 +4,11 @@ import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v7.widget.Toolbar;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.TextView;
@ -30,6 +32,7 @@ import eu.kanade.mangafeed.ui.reader.viewer.horizontal.RightToLeftReader;
import eu.kanade.mangafeed.ui.reader.viewer.vertical.VerticalReader;
import eu.kanade.mangafeed.ui.reader.viewer.webtoon.WebtoonReader;
import eu.kanade.mangafeed.util.ToastUtil;
import icepick.Icepick;
import nucleus.factory.RequiresPresenter;
@RequiresPresenter(ReaderPresenter.class)
@ -66,10 +69,20 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
setupToolbar(toolbar);
readerMenu = new ReaderMenu(this, prefs);
Icepick.restoreInstanceState(readerMenu, savedState);
if (savedState != null && readerMenu.showing)
readerMenu.show(false);
createUiHideFlags();
enableHardwareAcceleration();
}
@Override
protected void onDestroy() {
readerMenu.destroy();
super.onDestroy();
}
@Override
protected void onResume() {
super.onResume();
@ -83,11 +96,17 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
super.onPause();
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
Icepick.saveInstanceState(readerMenu, outState);
super.onSaveInstanceState(outState);
}
private void createUiHideFlags() {
uiFlags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
if (prefs.isHideStatusBarSet())
uiFlags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
uiFlags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
@ -131,18 +150,22 @@ public class ReaderActivity extends BaseRxActivity<ReaderPresenter> {
readerMenu.toggle();
}
public ViewGroup getContainer() {
return container;
}
private BaseReader getViewer(Manga manga) {
int mangaViewer = manga.viewer == 0 ? prefs.getDefaultViewer() : manga.viewer;
switch (mangaViewer) {
case LEFT_TO_RIGHT: default:
return new LeftToRightReader(this, container);
return new LeftToRightReader(this);
case RIGHT_TO_LEFT:
return new RightToLeftReader(this, container);
return new RightToLeftReader(this);
case VERTICAL:
return new VerticalReader(this, container);
return new VerticalReader(this);
case WEBTOON:
return new WebtoonReader(this, container);
return new WebtoonReader(this);
}
}

View file

@ -1,9 +1,16 @@
package eu.kanade.mangafeed.ui.reader;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.view.Surface;
import android.view.View;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
@ -17,6 +24,8 @@ import eu.kanade.mangafeed.R;
import eu.kanade.mangafeed.data.database.models.Chapter;
import eu.kanade.mangafeed.data.database.models.Manga;
import eu.kanade.mangafeed.data.preference.PreferencesHelper;
import icepick.State;
import rx.subscriptions.CompositeSubscription;
public class ReaderMenu {
@ -26,41 +35,58 @@ public class ReaderMenu {
@Bind(R.id.current_page) TextView currentPage;
@Bind(R.id.page_seeker) SeekBar seekBar;
@Bind(R.id.total_pages) TextView totalPages;
@Bind(R.id.lock_orientation) ImageButton lockOrientation;
@Bind(R.id.reader_selector) ImageButton readerSelector;
private ReaderActivity activity;
private PreferencesHelper preferences;
private boolean showing;
@State boolean showing;
private DecimalFormat decimalFormat;
private CompositeSubscription subscriptions;
public ReaderMenu(ReaderActivity activity, PreferencesHelper preferences) {
this.activity = activity;
this.preferences = preferences;
ButterKnife.bind(this, activity);
// Intercept all image events in this layout
bottomMenu.setOnTouchListener((v, event) -> true);
seekBar.setOnSeekBarChangeListener(new PageSeekBarChangeListener());
decimalFormat = new DecimalFormat("#.##");
subscriptions = new CompositeSubscription();
initializeOptions();
}
public void destroy() {
subscriptions.unsubscribe();
}
public void toggle() {
if (showing)
hide();
else
show();
show(true);
}
private void show() {
public void show(boolean animate) {
menu.setVisibility(View.VISIBLE);
Animation toolbarAnimation = AnimationUtils.loadAnimation(activity, R.anim.enter_from_top);
toolbar.startAnimation(toolbarAnimation);
if (animate) {
Animation toolbarAnimation = AnimationUtils.loadAnimation(activity, R.anim.enter_from_top);
toolbar.startAnimation(toolbarAnimation);
Animation bottomMenuAnimation = AnimationUtils.loadAnimation(activity, R.anim.enter_from_bottom);
bottomMenu.startAnimation(bottomMenuAnimation);
Animation bottomMenuAnimation = AnimationUtils.loadAnimation(activity, R.anim.enter_from_bottom);
bottomMenu.startAnimation(bottomMenuAnimation);
}
showing = true;
}
private void hide() {
public void hide() {
Animation toolbarAnimation = AnimationUtils.loadAnimation(activity, R.anim.exit_to_top);
toolbarAnimation.setAnimationListener(new HideMenuAnimationListener());
toolbar.startAnimation(toolbarAnimation);
@ -77,9 +103,9 @@ public class ReaderMenu {
activity.setToolbarTitle(manga.title);
activity.setToolbarSubtitle(chapter.chapter_number != -1 ?
activity.getString(R.string.chapter_subtitle,
decimalFormat.format(chapter.chapter_number)) :
chapter.name);
activity.getString(R.string.chapter_subtitle,
decimalFormat.format(chapter.chapter_number)) :
chapter.name);
}
@ -88,6 +114,73 @@ public class ReaderMenu {
seekBar.setProgress(pageIndex);
}
private void initializeOptions() {
// Orientation changes
lockOrientation.setOnClickListener(v ->
preferences.setOrientationLocked(!preferences.isOrientationLocked()));
subscriptions.add(preferences.isOrientationLockedObservable()
.subscribe(this::onOrientationOptionChanged));
// Reader selector
readerSelector.setOnClickListener(v -> {
final Manga manga = activity.getPresenter().getManga();
final Dialog dialog = new AlertDialog.Builder(activity)
.setSingleChoiceItems(R.array.viewers_selector, manga.viewer, (d, which) -> {
if (manga.viewer != which) {
activity.getPresenter().updateMangaViewer(which);
activity.recreate();
}
d.dismiss();
})
.create();
// Hack to not leave immersive mode
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
dialog.getWindow().getDecorView().setSystemUiVisibility(
activity.getWindow().getDecorView().getSystemUiVisibility());
dialog.show();
dialog.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
WindowManager wm = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);
wm.updateViewLayout(activity.getWindow().getDecorView(), activity.getWindow().getAttributes());
});
}
private void onOrientationOptionChanged(boolean locked) {
if (locked)
lockOrientation();
else
activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
int resourceId = !locked ? R.drawable.ic_screen_rotation :
activity.getResources().getConfiguration().orientation == 1 ?
R.drawable.ic_screen_lock_portrait :
R.drawable.ic_screen_lock_landscape;
lockOrientation.setImageResource(resourceId);
}
private void lockOrientation() {
int orientation;
int rotation = ((WindowManager) activity.getSystemService(
Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation();
switch (rotation) {
case Surface.ROTATION_0:
orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
break;
case Surface.ROTATION_90:
orientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
break;
case Surface.ROTATION_180:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT;
break;
default:
orientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE;
break;
}
activity.setRequestedOrientation(orientation);
}
class PageSeekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
@Override

View file

@ -232,4 +232,13 @@ public class ReaderPresenter extends BasePresenter<ReaderActivity> {
loadChapter(previousChapter);
}
}
public Manga getManga() {
return manga;
}
public void updateMangaViewer(int viewer) {
manga.viewer = viewer;
db.insertManga(manga).executeAsBlocking();
}
}

View file

@ -1,7 +1,7 @@
package eu.kanade.mangafeed.ui.reader.viewer.base;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.view.ViewGroup;
import java.util.List;
@ -11,12 +11,12 @@ import eu.kanade.mangafeed.ui.reader.ReaderActivity;
public abstract class BaseReader {
protected ReaderActivity activity;
protected FrameLayout container;
protected ViewGroup container;
protected int currentPosition;
public BaseReader(ReaderActivity activity, FrameLayout container) {
public BaseReader(ReaderActivity activity) {
this.activity = activity;
this.container = container;
this.container = activity.getContainer();
}
public void updatePageNumber() {

View file

@ -1,7 +1,6 @@
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import java.util.List;
@ -19,8 +18,8 @@ public abstract class HorizontalReader extends BaseReader {
protected ViewPagerReaderAdapter adapter;
public HorizontalReader(ReaderActivity activity, FrameLayout container) {
super(activity, container);
public HorizontalReader(ReaderActivity activity) {
super(activity);
activity.getLayoutInflater().inflate(R.layout.reader_horizontal, container);
ButterKnife.bind(this, container);

View file

@ -1,13 +1,11 @@
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
import android.widget.FrameLayout;
import eu.kanade.mangafeed.ui.reader.ReaderActivity;
public class LeftToRightReader extends HorizontalReader {
public LeftToRightReader(ReaderActivity activity, FrameLayout container) {
super(activity, container);
public LeftToRightReader(ReaderActivity activity) {
super(activity);
}
@Override

View file

@ -1,7 +1,5 @@
package eu.kanade.mangafeed.ui.reader.viewer.horizontal;
import android.widget.FrameLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@ -11,8 +9,8 @@ import eu.kanade.mangafeed.ui.reader.ReaderActivity;
public class RightToLeftReader extends HorizontalReader {
public RightToLeftReader(ReaderActivity activity, FrameLayout container) {
super(activity, container);
public RightToLeftReader(ReaderActivity activity) {
super(activity);
}
@Override

View file

@ -2,7 +2,6 @@ package eu.kanade.mangafeed.ui.reader.viewer.vertical;
import android.support.v4.view.ViewPager;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import java.util.List;
@ -20,8 +19,8 @@ public class VerticalReader extends BaseReader {
private ViewPagerReaderAdapter adapter;
public VerticalReader(ReaderActivity activity, FrameLayout container) {
super(activity, container);
public VerticalReader(ReaderActivity activity) {
super(activity);
activity.getLayoutInflater().inflate(R.layout.reader_vertical, container);
ButterKnife.bind(this, container);

View file

@ -3,7 +3,6 @@ package eu.kanade.mangafeed.ui.reader.viewer.webtoon;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import java.util.List;
@ -22,8 +21,8 @@ public class WebtoonReader extends BaseReader {
private List<Page> pages;
private Subscription subscription;
public WebtoonReader(ReaderActivity activity, FrameLayout container) {
super(activity, container);
public WebtoonReader(ReaderActivity activity) {
super(activity);
recycler = new RecyclerView(activity);
layoutManager = new LinearLayoutManager(activity);

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 156 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 327 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 269 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 578 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 482 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 381 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 388 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 643 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 280 B

View file

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/reader_menu"
android:visibility="gone">
android:visibility="gone"
tools:visibility="visible">
<include layout="@layout/toolbar"/>
@ -12,32 +14,79 @@
android:layout_height="wrap_content"
android:id="@+id/reader_menu_bottom"
android:background="@color/reader_menu_background"
android:orientation="vertical"
android:layout_alignParentBottom="true">
<TextView
android:id="@+id/current_page"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_gravity="center_vertical"
android:textColor="@color/light_grey"
android:gravity="center_horizontal" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SeekBar
android:id="@+id/page_seeker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/current_page"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_gravity="center_vertical"
android:textColor="@color/light_grey"
android:gravity="center_horizontal"
android:layout_marginTop="12dp"
android:layout_marginBottom="12dp" />
<TextView
android:id="@+id/total_pages"
android:layout_width="32dp"
<SeekBar
android:id="@+id/page_seeker"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_gravity="center_vertical" />
<TextView
android:id="@+id/total_pages"
android:layout_width="32dp"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_gravity="center_vertical"
android:textColor="@color/light_grey"
android:gravity="center_horizontal" />
</LinearLayout>
<View android:background="#777777"
android:layout_width="match_parent"
android:layout_height="1dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginRight="8dp"
android:layout_gravity="center_vertical"
android:textColor="@color/light_grey"
android:gravity="center_horizontal" />
android:gravity="center_horizontal"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp">
<ImageButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/lock_orientation"
android:src="@drawable/ic_screen_rotation"
android:background="?android:selectableItemBackground" />
<ImageButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:selectableItemBackground" />
<ImageButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="?android:selectableItemBackground" />
<ImageButton
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:id="@+id/reader_selector"
android:src="@drawable/ic_view_carousel"
android:background="?android:selectableItemBackground" />
</LinearLayout>
</LinearLayout>

View file

@ -14,10 +14,17 @@
<item>4</item>
</string-array>
<string-array name="viewers_selector">
<item>@string/default_viewer</item>
<item>@string/left_to_right_viewer</item>
<item>@string/right_to_left_viewer</item>
<item>@string/vertical_viewer</item>
<item>@string/webtoon_viewer</item>
</string-array>
<string-array name="download_threads">
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
</resources>

View file

@ -4,6 +4,7 @@
<string name="pref_category_accounts_key">pref_category_accounts_key</string>
<string name="pref_category_downloads_key">pref_category_downloads_key</string>
<string name="pref_hide_status_bar_key">pref_hide_status_bar_key</string>
<string name="pref_lock_orientation_key">pref_lock_orientation_key</string>
<string name="pref_default_viewer_key">pref_default_viewer_key</string>
<string name="pref_download_directory_key">pref_download_directory_key</string>
<string name="pref_download_threads_key">pref_download_threads_key</string>

View file

@ -29,6 +29,7 @@
<!-- Reader section -->
<string name="pref_hide_status_bar">Hide status bar</string>
<string name="pref_viewer_type">Default viewer</string>
<string name="default_viewer">Default</string>
<string name="left_to_right_viewer">Left to right</string>
<string name="right_to_left_viewer">Right to left</string>
<string name="vertical_viewer">Vertical</string>
@ -82,5 +83,6 @@
<string name="notification_completed">Update completed</string>
<string name="notification_no_new_chapters">No new chapters found</string>
<string name="notification_new_chapters">Found new chapters for:</string>
<string name="pref_lock_orientation">Lock orientation</string>
</resources>

View file

@ -5,6 +5,10 @@
android:key="@string/pref_hide_status_bar_key"
android:defaultValue="true" />
<CheckBoxPreference android:title="@string/pref_lock_orientation"
android:key="@string/pref_lock_orientation_key"
android:defaultValue="true" />
<ListPreference android:title="@string/pref_viewer_type"
android:key="@string/pref_default_viewer_key"
android:entries="@array/viewers"