Add minor improvements and retry button to webtoon reader.
This commit is contained in:
parent
39c9fd5945
commit
b735a1f581
7 changed files with 175 additions and 84 deletions
|
@ -51,7 +51,7 @@ public class PagerReaderFragment extends BaseFragment {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_page, container, false);
|
View view = inflater.inflate(R.layout.item_pager_reader, container, false);
|
||||||
ButterKnife.bind(this, view);
|
ButterKnife.bind(this, view);
|
||||||
ReaderActivity activity = (ReaderActivity) getActivity();
|
ReaderActivity activity = (ReaderActivity) getActivity();
|
||||||
|
|
||||||
|
|
|
@ -4,31 +4,23 @@ import android.support.v7.widget.RecyclerView;
|
||||||
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 android.view.animation.Animation;
|
|
||||||
import android.view.animation.AnimationUtils;
|
|
||||||
import android.widget.ProgressBar;
|
|
||||||
|
|
||||||
import com.davemorrissey.labs.subscaleview.ImageSource;
|
|
||||||
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import butterknife.Bind;
|
|
||||||
import butterknife.ButterKnife;
|
|
||||||
import eu.kanade.mangafeed.R;
|
import eu.kanade.mangafeed.R;
|
||||||
import eu.kanade.mangafeed.data.source.model.Page;
|
import eu.kanade.mangafeed.data.source.model.Page;
|
||||||
|
|
||||||
public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonAdapter.ImageHolder> {
|
public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonHolder> {
|
||||||
|
|
||||||
private List<Page> pages;
|
|
||||||
private WebtoonReader fragment;
|
private WebtoonReader fragment;
|
||||||
private View.OnTouchListener listener;
|
private List<Page> pages;
|
||||||
|
private View.OnTouchListener touchListener;
|
||||||
|
|
||||||
public WebtoonAdapter(WebtoonReader fragment) {
|
public WebtoonAdapter(WebtoonReader fragment) {
|
||||||
this.fragment = fragment;
|
this.fragment = fragment;
|
||||||
pages = new ArrayList<>();
|
pages = new ArrayList<>();
|
||||||
listener = (v, event) -> fragment.onImageTouch(event);
|
touchListener = (v, event) -> fragment.onImageTouch(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page getItem(int position) {
|
public Page getItem(int position) {
|
||||||
|
@ -36,14 +28,14 @@ public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonAdapter.ImageHol
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImageHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public WebtoonHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
LayoutInflater inflater = fragment.getActivity().getLayoutInflater();
|
LayoutInflater inflater = fragment.getActivity().getLayoutInflater();
|
||||||
View v = inflater.inflate(R.layout.item_webtoon_reader, parent, false);
|
View v = inflater.inflate(R.layout.item_webtoon_reader, parent, false);
|
||||||
return new ImageHolder(v, listener);
|
return new WebtoonHolder(v, this, touchListener);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ImageHolder holder, int position) {
|
public void onBindViewHolder(WebtoonHolder holder, int position) {
|
||||||
final Page page = getItem(position);
|
final Page page = getItem(position);
|
||||||
holder.onSetValues(page);
|
holder.onSetValues(page);
|
||||||
}
|
}
|
||||||
|
@ -53,9 +45,9 @@ public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonAdapter.ImageHol
|
||||||
return pages.size();
|
return pages.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPage(Page page) {
|
public void setPages(List<Page> pages) {
|
||||||
pages.add(page);
|
this.pages = pages;
|
||||||
notifyItemInserted(page.getPageNumber());
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
|
@ -65,41 +57,8 @@ public class WebtoonAdapter extends RecyclerView.Adapter<WebtoonAdapter.ImageHol
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ImageHolder extends RecyclerView.ViewHolder {
|
public void retryPage(Page page) {
|
||||||
|
fragment.getReaderActivity().getPresenter().retryPage(page);
|
||||||
@Bind(R.id.page_image_view) SubsamplingScaleImageView imageView;
|
|
||||||
@Bind(R.id.progress) ProgressBar progressBar;
|
|
||||||
|
|
||||||
private Animation fadeInAnimation;
|
|
||||||
|
|
||||||
public ImageHolder(View view, View.OnTouchListener listener) {
|
|
||||||
super(view);
|
|
||||||
ButterKnife.bind(this, view);
|
|
||||||
|
|
||||||
fadeInAnimation = AnimationUtils.loadAnimation(view.getContext(), R.anim.fade_in);
|
|
||||||
|
|
||||||
imageView.setParallelLoadingEnabled(true);
|
|
||||||
imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED);
|
|
||||||
imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
|
|
||||||
imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE);
|
|
||||||
imageView.setOnTouchListener(listener);
|
|
||||||
imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
|
|
||||||
@Override
|
|
||||||
public void onImageLoaded() {
|
|
||||||
imageView.startAnimation(fadeInAnimation);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSetValues(Page page) {
|
|
||||||
if (page.getImagePath() != null) {
|
|
||||||
imageView.setVisibility(View.VISIBLE);
|
|
||||||
imageView.setImage(ImageSource.uri(page.getImagePath()));
|
|
||||||
progressBar.setVisibility(View.GONE);
|
|
||||||
} else {
|
|
||||||
imageView.setVisibility(View.GONE);
|
|
||||||
progressBar.setVisibility(View.VISIBLE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,117 @@
|
||||||
|
package eu.kanade.mangafeed.ui.reader.viewer.webtoon;
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.view.animation.Animation;
|
||||||
|
import android.view.animation.AnimationUtils;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
|
import com.davemorrissey.labs.subscaleview.ImageSource;
|
||||||
|
import com.davemorrissey.labs.subscaleview.SubsamplingScaleImageView;
|
||||||
|
|
||||||
|
import butterknife.Bind;
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import eu.kanade.mangafeed.R;
|
||||||
|
import eu.kanade.mangafeed.data.source.model.Page;
|
||||||
|
|
||||||
|
public class WebtoonHolder extends RecyclerView.ViewHolder {
|
||||||
|
|
||||||
|
@Bind(R.id.page_image_view) SubsamplingScaleImageView imageView;
|
||||||
|
@Bind(R.id.frame_container) ViewGroup container;
|
||||||
|
@Bind(R.id.progress) ProgressBar progressBar;
|
||||||
|
@Bind(R.id.retry_button) Button retryButton;
|
||||||
|
|
||||||
|
private Animation fadeInAnimation;
|
||||||
|
private Page page;
|
||||||
|
|
||||||
|
public WebtoonHolder(View view, WebtoonAdapter adapter, View.OnTouchListener touchListener) {
|
||||||
|
super(view);
|
||||||
|
ButterKnife.bind(this, view);
|
||||||
|
|
||||||
|
fadeInAnimation = AnimationUtils.loadAnimation(view.getContext(), R.anim.fade_in);
|
||||||
|
|
||||||
|
imageView.setParallelLoadingEnabled(true);
|
||||||
|
imageView.setDoubleTapZoomStyle(SubsamplingScaleImageView.ZOOM_FOCUS_FIXED);
|
||||||
|
imageView.setPanLimit(SubsamplingScaleImageView.PAN_LIMIT_INSIDE);
|
||||||
|
imageView.setMinimumScaleType(SubsamplingScaleImageView.SCALE_TYPE_CENTER_INSIDE);
|
||||||
|
imageView.setOnTouchListener(touchListener);
|
||||||
|
imageView.setOnImageEventListener(new SubsamplingScaleImageView.DefaultOnImageEventListener() {
|
||||||
|
@Override
|
||||||
|
public void onImageLoaded() {
|
||||||
|
imageView.startAnimation(fadeInAnimation);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
progressBar.setMinimumHeight(view.getResources().getDisplayMetrics().heightPixels);
|
||||||
|
|
||||||
|
container.setOnTouchListener(touchListener);
|
||||||
|
retryButton.setOnTouchListener((v, event) -> {
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
|
if (page != null)
|
||||||
|
adapter.retryPage(page);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onSetValues(Page page) {
|
||||||
|
this.page = page;
|
||||||
|
switch (page.getStatus()) {
|
||||||
|
case Page.QUEUE:
|
||||||
|
onQueue();
|
||||||
|
break;
|
||||||
|
case Page.LOAD_PAGE:
|
||||||
|
onLoading();
|
||||||
|
break;
|
||||||
|
case Page.DOWNLOAD_IMAGE:
|
||||||
|
onLoading();
|
||||||
|
break;
|
||||||
|
case Page.READY:
|
||||||
|
onReady();
|
||||||
|
break;
|
||||||
|
case Page.ERROR:
|
||||||
|
onError();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onLoading() {
|
||||||
|
setErrorButtonVisible(false);
|
||||||
|
setImageVisible(false);
|
||||||
|
setProgressVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onReady() {
|
||||||
|
setErrorButtonVisible(false);
|
||||||
|
setProgressVisible(false);
|
||||||
|
setImageVisible(true);
|
||||||
|
imageView.setImage(ImageSource.uri(page.getImagePath()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onError() {
|
||||||
|
setImageVisible(false);
|
||||||
|
setProgressVisible(false);
|
||||||
|
setErrorButtonVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onQueue() {
|
||||||
|
setImageVisible(false);
|
||||||
|
setErrorButtonVisible(false);
|
||||||
|
setProgressVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setProgressVisible(boolean visible) {
|
||||||
|
progressBar.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setImageVisible(boolean visible) {
|
||||||
|
imageView.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setErrorButtonVisible(boolean visible) {
|
||||||
|
retryButton.setVisibility(visible ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
|
@ -25,6 +25,7 @@ public class WebtoonReader extends BaseReader {
|
||||||
|
|
||||||
private WebtoonAdapter adapter;
|
private WebtoonAdapter adapter;
|
||||||
private RecyclerView recycler;
|
private RecyclerView recycler;
|
||||||
|
private PreCachingLayoutManager layoutManager;
|
||||||
private Subscription subscription;
|
private Subscription subscription;
|
||||||
private GestureDetector gestureDetector;
|
private GestureDetector gestureDetector;
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ public class WebtoonReader extends BaseReader {
|
||||||
@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);
|
||||||
PreCachingLayoutManager layoutManager = new PreCachingLayoutManager(getActivity());
|
layoutManager = new PreCachingLayoutManager(getActivity());
|
||||||
layoutManager.setExtraLayoutSpace(getResources().getDisplayMetrics().heightPixels);
|
layoutManager.setExtraLayoutSpace(getResources().getDisplayMetrics().heightPixels);
|
||||||
|
|
||||||
recycler = new RecyclerView(getActivity());
|
recycler = new RecyclerView(getActivity());
|
||||||
|
@ -40,15 +41,6 @@ public class WebtoonReader extends BaseReader {
|
||||||
recycler.setLayoutManager(layoutManager);
|
recycler.setLayoutManager(layoutManager);
|
||||||
recycler.setItemAnimator(null);
|
recycler.setItemAnimator(null);
|
||||||
recycler.setAdapter(adapter);
|
recycler.setAdapter(adapter);
|
||||||
recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
|
||||||
@Override
|
|
||||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
|
||||||
super.onScrolled(recyclerView, dx, dy);
|
|
||||||
|
|
||||||
currentPage = layoutManager.findLastVisibleItemPosition();
|
|
||||||
updatePageNumber();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
gestureDetector = new GestureDetector(getActivity(), new SimpleOnGestureListener() {
|
gestureDetector = new GestureDetector(getActivity(), new SimpleOnGestureListener() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,11 +92,27 @@ public class WebtoonReader extends BaseReader {
|
||||||
private void setPages() {
|
private void setPages() {
|
||||||
if (pages != null) {
|
if (pages != null) {
|
||||||
unsubscribeStatus();
|
unsubscribeStatus();
|
||||||
|
recycler.clearOnScrollListeners();
|
||||||
adapter.clear();
|
adapter.clear();
|
||||||
|
recycler.scrollTo(0, 0);
|
||||||
|
adapter.setPages(pages);
|
||||||
|
setScrollListener();
|
||||||
observeStatus(0);
|
observeStatus(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setScrollListener() {
|
||||||
|
recycler.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||||
|
super.onScrolled(recyclerView, dx, dy);
|
||||||
|
|
||||||
|
currentPage = layoutManager.findLastVisibleItemPosition();
|
||||||
|
updatePageNumber();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onImageTouch(MotionEvent motionEvent) {
|
public boolean onImageTouch(MotionEvent motionEvent) {
|
||||||
return gestureDetector.onTouchEvent(motionEvent);
|
return gestureDetector.onTouchEvent(motionEvent);
|
||||||
|
@ -115,7 +123,6 @@ public class WebtoonReader extends BaseReader {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final Page page = pages.get(position);
|
final Page page = pages.get(position);
|
||||||
adapter.addPage(page);
|
|
||||||
|
|
||||||
PublishSubject<Integer> statusSubject = PublishSubject.create();
|
PublishSubject<Integer> statusSubject = PublishSubject.create();
|
||||||
page.setStatusSubject(statusSubject);
|
page.setStatusSubject(statusSubject);
|
||||||
|
@ -130,17 +137,9 @@ public class WebtoonReader extends BaseReader {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void processStatus(int position, int status) {
|
private void processStatus(int position, int status) {
|
||||||
switch (status) {
|
|
||||||
case Page.LOAD_PAGE:
|
|
||||||
break;
|
|
||||||
case Page.DOWNLOAD_IMAGE:
|
|
||||||
break;
|
|
||||||
case Page.READY:
|
|
||||||
adapter.notifyItemChanged(position);
|
adapter.notifyItemChanged(position);
|
||||||
|
if (status == Page.READY) {
|
||||||
observeStatus(position + 1);
|
observeStatus(position + 1);
|
||||||
break;
|
|
||||||
case Page.ERROR:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:id="@+id/retry_button"
|
android:id="@+id/retry_button"
|
||||||
android:text="Retry"
|
android:text="@string/action_retry"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
android:visibility="gone"/>
|
android:visibility="gone"/>
|
||||||
|
|
|
@ -4,6 +4,11 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="300dp"
|
||||||
|
android:id="@+id/frame_container">
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress"
|
android:id="@+id/progress"
|
||||||
style="?android:attr/progressBarStyleLarge"
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
@ -11,6 +16,16 @@
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="center_vertical|center_horizontal"/>
|
android:layout_gravity="center_vertical|center_horizontal"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/retry_button"
|
||||||
|
android:text="@string/action_retry"
|
||||||
|
android:layout_gravity="center_vertical|center_horizontal"
|
||||||
|
android:visibility="gone" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
||||||
<include layout="@layout/chapter_image"/>
|
<include layout="@layout/chapter_image"/>
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
|
@ -36,6 +36,7 @@
|
||||||
<string name="action_stop">Stop</string>
|
<string name="action_stop">Stop</string>
|
||||||
<string name="action_previous_chapter">Previous chapter</string>
|
<string name="action_previous_chapter">Previous chapter</string>
|
||||||
<string name="action_next_chapter">Next chapter</string>
|
<string name="action_next_chapter">Next chapter</string>
|
||||||
|
<string name="action_retry">Retry</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Buttons -->
|
<!-- Buttons -->
|
||||||
|
|
Reference in a new issue