Fix gestures on vertical readers

This commit is contained in:
inorichi 2016-01-30 16:40:41 +01:00
parent bcefc176c1
commit e53b05feba
6 changed files with 61 additions and 51 deletions

View file

@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.source.model.Page; import eu.kanade.tachiyomi.data.source.model.Page;
import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment; import eu.kanade.tachiyomi.ui.base.fragment.BaseFragment;
import eu.kanade.tachiyomi.ui.reader.ReaderActivity; import eu.kanade.tachiyomi.ui.reader.ReaderActivity;
import eu.kanade.tachiyomi.ui.reader.viewer.pager.vertical.VerticalReader;
import rx.Observable; import rx.Observable;
import rx.Subscription; import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers; import rx.android.schedulers.AndroidSchedulers;
@ -61,12 +62,13 @@ public class PagerReaderFragment extends BaseFragment {
} }
imageView.setParallelLoadingEnabled(true); imageView.setParallelLoadingEnabled(true);
imageView.setMaxDimensions(activity.getMaxBitmapSize(), activity.getMaxBitmapSize()); imageView.setMaxBitmapDimensions(activity.getMaxBitmapSize());
imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED); imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED);
imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE); imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
imageView.setMinimumScaleType(parentFragment.scaleType); imageView.setMinimumScaleType(parentFragment.scaleType);
imageView.setRegionDecoderClass(parentFragment.getRegionDecoderClass()); imageView.setRegionDecoderClass(parentFragment.getRegionDecoderClass());
imageView.setBitmapDecoderClass(parentFragment.getBitmapDecoderClass()); imageView.setBitmapDecoderClass(parentFragment.getBitmapDecoderClass());
imageView.setVerticalScroll(parentFragment instanceof VerticalReader);
imageView.setOnTouchListener((v, motionEvent) -> parentFragment.onImageTouch(motionEvent)); imageView.setOnTouchListener((v, motionEvent) -> parentFragment.onImageTouch(motionEvent));
imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() { imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
@Override @Override

View file

@ -32,7 +32,7 @@ public class VerticalPager extends VerticalViewPagerImpl implements Pager {
} }
private void init(Context context) { private void init(Context context) {
gestureDetector = new GestureDetector(context, new VerticalPagerGestureListener(this)); gestureDetector = new GestureDetector(context, new PagerGestureListener(this));
} }
@Override @Override
@ -120,19 +120,4 @@ public class VerticalPager extends VerticalViewPagerImpl implements Pager {
}); });
} }
private static class VerticalPagerGestureListener extends PagerGestureListener {
public VerticalPagerGestureListener(Pager pager) {
super(pager);
}
@Override
public boolean onDown(MotionEvent e) {
// Vertical view pager ignores scrolling events sometimes.
// Returning true here fixes it, but we lose touch events on the image like
// double tap to zoom
return true;
}
}
} }

View file

@ -10,6 +10,7 @@ import java.util.List;
import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.source.model.Page; import eu.kanade.tachiyomi.data.source.model.Page;
import eu.kanade.tachiyomi.ui.reader.ReaderActivity;
public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonHolder> { public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonHolder> {
@ -64,4 +65,8 @@ public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonHolder> {
return fragment; return fragment;
} }
public ReaderActivity getReaderActivity() {
return (ReaderActivity) fragment.getActivity();
}
} }

View file

@ -14,7 +14,6 @@ import butterknife.Bind;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import eu.kanade.tachiyomi.R; import eu.kanade.tachiyomi.R;
import eu.kanade.tachiyomi.data.source.model.Page; import eu.kanade.tachiyomi.data.source.model.Page;
import eu.kanade.tachiyomi.ui.reader.ReaderActivity;
public class WebtoonHolder extends RecyclerView.ViewHolder { public class WebtoonHolder extends RecyclerView.ViewHolder {
@ -31,17 +30,16 @@ public class WebtoonHolder extends RecyclerView.ViewHolder {
this.adapter = adapter; this.adapter = adapter;
ButterKnife.bind(this, view); ButterKnife.bind(this, view);
int maxDim = ((ReaderActivity)adapter.getReader().getActivity()).getMaxBitmapSize();
imageView.setParallelLoadingEnabled(true); imageView.setParallelLoadingEnabled(true);
imageView.setMaxBitmapDimensions(adapter.getReaderActivity().getMaxBitmapSize());
imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED); imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED);
imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE); imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH); imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_FIT_WIDTH);
imageView.setMaxScale(10); imageView.setMaxScale(10);
imageView.setRegionDecoderClass(adapter.getReader().getRegionDecoderClass()); imageView.setRegionDecoderClass(adapter.getReader().getRegionDecoderClass());
imageView.setBitmapDecoderClass(adapter.getReader().getBitmapDecoderClass()); imageView.setBitmapDecoderClass(adapter.getReader().getBitmapDecoderClass());
imageView.setVerticalScroll(true);
imageView.setOnTouchListener(touchListener); imageView.setOnTouchListener(touchListener);
imageView.setMaxDimensions(maxDim, maxDim);
imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() { imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
@Override @Override
public void onImageLoaded() { public void onImageLoaded() {

View file

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.ui.reader.viewer.webtoon; package eu.kanade.tachiyomi.ui.reader.viewer.webtoon;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -30,7 +29,6 @@ public class WebtoonReader extends BaseReader {
private Subscription decoderSubscription; private Subscription decoderSubscription;
private GestureDetector gestureDetector; private GestureDetector gestureDetector;
@Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedState) {
adapter = new WebtoonAdapter(this); adapter = new WebtoonAdapter(this);
@ -56,14 +54,6 @@ public class WebtoonReader extends BaseReader {
getReaderActivity().onCenterSingleTap(); getReaderActivity().onCenterSingleTap();
return true; return true;
} }
@Override
public boolean onDown(MotionEvent e) {
// The only way I've found to allow panning. Double tap event (zoom) is lost
// but panning should be the most used one
return true;
}
}); });
setPages(); setPages();

View file

@ -201,8 +201,12 @@ public class SubsamplingScaleImageView extends View {
private int sOrientation; private int sOrientation;
private Rect sRegion; private Rect sRegion;
private Rect pRegion; private Rect pRegion;
private int cWidth;
private int cHeight; // Max bitmap dimensions the device can display
private int maxBitmapDimensions;
// Vertical pagers/scrollers should enable this
private boolean isVerticalScroll;
// Is two-finger zooming in progress // Is two-finger zooming in progress
private boolean isZooming; private boolean isZooming;
@ -754,16 +758,32 @@ public class SubsamplingScaleImageView extends View {
float lastX = vTranslate.x; float lastX = vTranslate.x;
float lastY = vTranslate.y; float lastY = vTranslate.y;
fitToBounds(true); fitToBounds(true);
boolean atXEdge = lastX != vTranslate.x; if (!isVerticalScroll) {
boolean edgeXSwipe = atXEdge && dx > dy && !isPanning; boolean atXEdge = lastX != vTranslate.x;
boolean yPan = lastY == vTranslate.y && dy > 15; boolean edgeXSwipe = atXEdge && dx > dy && !isPanning;
if (!edgeXSwipe && (!atXEdge || yPan || isPanning)) { boolean yPan = lastY == vTranslate.y && dy > 15;
isPanning = true;
} else if (dx > 5) { if (!edgeXSwipe && (!atXEdge || yPan || isPanning)) {
// Haven't panned the image, and we're at the left or right edge. Switch to page swipe. isPanning = true;
maxTouchCount = 0; } else if (dx > 5) {
handler.removeMessages(MESSAGE_LONG_CLICK); // Haven't panned the image, and we're at the left or right edge. Switch to page swipe.
getParent().requestDisallowInterceptTouchEvent(false); maxTouchCount = 0;
handler.removeMessages(MESSAGE_LONG_CLICK);
getParent().requestDisallowInterceptTouchEvent(false);
}
} else {
boolean atYEdge = lastY != vTranslate.y;
boolean edgeYSwipe = atYEdge && dy > dx && !isPanning;
boolean xPan = lastX == vTranslate.x && dx > 15;
if (!edgeYSwipe && (!atYEdge || xPan || isPanning)) {
isPanning = true;
} else if (dy > 5) {
// Haven't panned the image, and we're at the left or right edge. Switch to page swipe.
maxTouchCount = 0;
handler.removeMessages(MESSAGE_LONG_CLICK);
getParent().requestDisallowInterceptTouchEvent(false);
}
} }
if (!panEnabled) { if (!panEnabled) {
@ -870,7 +890,7 @@ public class SubsamplingScaleImageView extends View {
} }
// When using tiles, on first render with no tile map ready, initialise it and kick off async base image loading. // When using tiles, on first render with no tile map ready, initialise it and kick off async base image loading.
if (tileMap == null && decoder != null && cWidth == 0 && cHeight == 0) { if (tileMap == null && decoder != null && maxBitmapDimensions == 0) {
initialiseBaseLayer(getMaxBitmapDimensions(canvas)); initialiseBaseLayer(getMaxBitmapDimensions(canvas));
} }
@ -1390,11 +1410,6 @@ public class SubsamplingScaleImageView extends View {
} }
} }
public void setMaxDimensions(int width, int height) {
cWidth = width;
cHeight = height;
}
/** /**
* Async task used to get image details without blocking the UI thread. * Async task used to get image details without blocking the UI thread.
*/ */
@ -1473,8 +1488,8 @@ public class SubsamplingScaleImageView extends View {
this.sHeight = sHeight; this.sHeight = sHeight;
this.sOrientation = sOrientation; this.sOrientation = sOrientation;
checkReady(); checkReady();
if (!checkImageLoaded() && cWidth != 0 && cHeight != 0) { if (!checkImageLoaded() && maxBitmapDimensions > 0) {
initialiseBaseLayer(new Point(cWidth, cHeight)); initialiseBaseLayer(new Point(maxBitmapDimensions, maxBitmapDimensions));
} }
invalidate(); invalidate();
requestLayout(); requestLayout();
@ -2476,6 +2491,21 @@ public class SubsamplingScaleImageView extends View {
this.parallelLoadingEnabled = parallelLoadingEnabled; this.parallelLoadingEnabled = parallelLoadingEnabled;
} }
/**
* Set max bitmap dimensions the device can display
*/
public void setMaxBitmapDimensions(int maxBitmapDimensions) {
this.maxBitmapDimensions = maxBitmapDimensions;
}
/**
* Set vertical scroll mode to fix gestures
*/
public void setVerticalScroll(boolean isVerticalScroll) {
this.isVerticalScroll = isVerticalScroll;
}
/** /**
* Enables visual debugging, showing tile boundaries and sizes. * Enables visual debugging, showing tile boundaries and sizes.
*/ */