优化阅读体验

pull/5/head
fengyuecanzhu 4 years ago
parent 9b6334bab6
commit 635dd06a54
  1. 5
      app/src/main/assets/updatelog.fy
  2. 68
      app/src/main/java/xyz/fycz/myreader/ui/activity/BookDetailedActivity.java
  3. 67
      app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java
  4. 161
      app/src/main/java/xyz/fycz/myreader/ui/activity/ReadActivity.java
  5. 6
      app/src/main/java/xyz/fycz/myreader/ui/fragment/BookcaseFragment.java
  6. 6
      app/src/main/java/xyz/fycz/myreader/ui/popmenu/ReadSettingMenu.java
  7. 50
      app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
  8. 28
      app/src/main/java/xyz/fycz/myreader/util/utils/StringUtils.java
  9. 12
      app/src/main/java/xyz/fycz/myreader/webapi/CommonApi.java
  10. 4
      app/src/main/java/xyz/fycz/myreader/webapi/callback/ResultCallback.java
  11. 58
      app/src/main/java/xyz/fycz/myreader/webapi/crawler/read/YanQingLouReadCrawler.java
  12. 5
      app/src/main/java/xyz/fycz/myreader/widget/page/LocalPageLoader.java
  13. 48
      app/src/main/java/xyz/fycz/myreader/widget/page/NetPageLoader.java
  14. 48
      app/src/main/java/xyz/fycz/myreader/widget/page/PageLoader.java
  15. 8
      app/src/main/res/drawable/ic_group.xml
  16. 231
      app/src/main/res/layout/fragment_bookcase.xml
  17. 225
      app/src/main/res/layout/gridview_book_detailed_item.xml
  18. 4
      app/src/main/res/layout/gridview_book_item.xml
  19. 15
      app/src/main/res/layout/view_empty.xml
  20. 10
      app/src/main/res/menu/menu_book.xml
  21. 17
      app/src/main/res/menu/menu_book_detail_local.xml
  22. 2
      app/src/main/res/values/strings.xml
  23. 2
      app/version_code.properties

@ -1,3 +1,8 @@
风月读书v1.8.2
1、优化阅读体验
2、修复已知bug
3、支持分享本地书籍(txt)
2020.02.01
风月读书v1.8.1
1、新增书源:笔尖小说、言情楼、卧龙小说

@ -58,6 +58,7 @@ import xyz.fycz.myreader.ui.dialog.BookGroupDialog;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog;
import xyz.fycz.myreader.util.IOUtils;
import xyz.fycz.myreader.util.ShareUtils;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.ToastUtils;
@ -494,23 +495,29 @@ public class BookDetailedActivity extends BaseActivity {
@Override
public boolean onCreateOptionsMenu(Menu menu) {
if ("本地书籍".equals(mBook.getType())) {
return false;
getMenuInflater().inflate(R.menu.menu_book_detail_local, menu);
} else {
getMenuInflater().inflate(R.menu.menu_book_detail, menu);
}
getMenuInflater().inflate(R.menu.menu_book_detail, menu);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
MenuItem isUpdate = menu.findItem(R.id.action_is_update);
MenuItem groupSetting = menu.findItem(R.id.action_group_setting);
if (isCollected) {
isUpdate.setVisible(true);
//groupSetting.setVisible(true);
isUpdate.setChecked(!mBook.getIsCloseUpdate());
if ("本地书籍".equals(mBook.getType())) {
MenuItem groupSetting = menu.findItem(R.id.action_group_setting);
groupSetting.setVisible(isCollected);
} else {
isUpdate.setVisible(false);
groupSetting.setVisible(false);
MenuItem isUpdate = menu.findItem(R.id.action_is_update);
MenuItem groupSetting = menu.findItem(R.id.action_group_setting);
if (isCollected) {
isUpdate.setVisible(true);
groupSetting.setVisible(true);
isUpdate.setChecked(!mBook.getIsCloseUpdate());
} else {
isUpdate.setVisible(false);
groupSetting.setVisible(false);
}
}
return super.onPrepareOptionsMenu(menu);
}
@ -632,7 +639,23 @@ public class BookDetailedActivity extends BaseActivity {
/**
* 分享书籍
*/
private void shareBook() {
if ("本地书籍".equals(mBook.getType())) {
File file = new File(mBook.getChapterUrl());
if (!file.exists()){
ToastUtils.showWarring("书籍源文件不存在,无法分享!");
return;
}
try {
ShareUtils.share(this, file, mBook.getName() + ".txt", "text/plain");
} catch (Exception e) {
String dest = APPCONST.SHARE_FILE_DIR + File.separator + mBook.getName() + ".txt";
FileUtils.copy(mBook.getChapterUrl(), dest);
ShareUtils.share(this, new File(dest), mBook.getName() + ".txt", "text/plain");
}
return;
}
ToastUtils.showInfo("正在生成分享图片");
Single.create((SingleOnSubscribe<File>) emitter -> {
// 使用url
@ -660,16 +683,17 @@ public class BookDetailedActivity extends BaseActivity {
}
emitter.onSuccess(share);
}).compose(RxUtils::toSimpleSingle)
.subscribe(new MySingleObserver<File>() {
@Override
public void onSuccess(@NonNull File File) {
share(File);
}
});
.subscribe(new MySingleObserver<File>() {
@Override
public void onSuccess(@NonNull File File) {
share(File);
}
});
}
/**
* 生成分享图片
*
* @param QRCode
* @return
*/
@ -745,21 +769,16 @@ public class BookDetailedActivity extends BaseActivity {
/**
* 分享生成的图片
*
* @param share
*/
private void share(File share) {
//noinspection ResultOfMethodCallIgnored
share.setReadable(true, false);
Uri contentUri = FileProvider.getUriForFile(this, BuildConfig.APPLICATION_ID + ".fileprovider", share);
final Intent intent = new Intent(Intent.ACTION_SEND);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra(Intent.EXTRA_STREAM, contentUri);
intent.setType("image/png");
startActivity(Intent.createChooser(intent, "分享书籍"));
ShareUtils.share(this, share, "分享书籍", "image/png");
}
/**
* 绘制简介
*
* @param lines
* @param textPaint
* @param canvas
@ -777,6 +796,7 @@ public class BookDetailedActivity extends BaseActivity {
/**
* 生成简介lines
*
* @param width
* @param textPaint
* @return

@ -9,6 +9,9 @@ import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
@ -63,6 +66,8 @@ public class MainActivity extends BaseActivity {
private BookcaseFragment mBookcaseFragment;
private FindFragment mFindFragment;
private MineFragment mMineFragment;
private Animation mBottomInAnim;
private Animation mBottomOutAnim;
@Override
protected void bindView() {
@ -73,7 +78,7 @@ public class MainActivity extends BaseActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
boolean startFromSplash = getIntent().getBooleanExtra("startFromSplash", false);
if (!startFromSplash && BookGroupService.getInstance().curGroupIsPrivate()){
if (!startFromSplash && BookGroupService.getInstance().curGroupIsPrivate()) {
SharedPreUtils.getInstance().putString(getString(R.string.curBookGroupId), "");
SharedPreUtils.getInstance().putString(getString(R.string.curBookGroupName), "");
}
@ -130,7 +135,7 @@ public class MainActivity extends BaseActivity {
super.initClick();
mToolbar.setOnLongClickListener(v -> {
if (binding.viewPagerMain.getCurrentItem() == 0 && !BookGroupService.getInstance().curGroupIsPrivate()){
if (binding.viewPagerMain.getCurrentItem() == 0 && !BookGroupService.getInstance().curGroupIsPrivate()) {
goPrivateBookcase();
return true;
}
@ -237,8 +242,11 @@ public class MainActivity extends BaseActivity {
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean isEdit = mBookcaseFragment.getmBookcasePresenter() != null && mBookcaseFragment.getmBookcasePresenter().ismEditState();
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
menu.findItem(R.id.action_refresh).setVisible(!isEdit);
}
if (binding.viewPagerMain.getCurrentItem() == 0) {
if (mBookcaseFragment.getmBookcasePresenter() != null && mBookcaseFragment.getmBookcasePresenter().ismEditState()) {
menu.findItem(R.id.action_finish).setVisible(true);
menu.setGroupVisible(R.id.bookcase_menu, false);
@ -270,8 +278,7 @@ public class MainActivity extends BaseActivity {
startActivity(searchBookIntent);
return true;
} else if (itemId == R.id.action_finish) {
mBookcaseFragment.getmBookcasePresenter().cancelEdit();
invalidateOptionsMenu();
cancelEdit();
return true;
} else if (itemId == R.id.action_change_group || itemId == R.id.action_group_man) {
if (!mBookcaseFragment.getmBookcasePresenter().hasOnGroupChangeListener()) {
@ -280,8 +287,13 @@ public class MainActivity extends BaseActivity {
getSupportActionBar().setSubtitle(groupName);
});
}
} else if (itemId == R.id.action_refresh) {
mBookcaseFragment.getmBookcasePresenter().initNoReadNum();
} else if (itemId == R.id.action_edit) {
invalidateOptionsMenu();
initMenuAnim();
binding.bottomNavigationView.setVisibility(View.GONE);
binding.bottomNavigationView.startAnimation(mBottomOutAnim);
} else if (itemId == R.id.action_qr_scan) {
Intent intent = new Intent(this, QRCodeScanActivity.class);
startActivityForResult(intent, APPCONST.REQUEST_QR_SCAN);
@ -292,8 +304,7 @@ public class MainActivity extends BaseActivity {
@Override
public void onBackPressed() {
if (mBookcaseFragment.getmBookcasePresenter() != null && mBookcaseFragment.getmBookcasePresenter().ismEditState()) {
mBookcaseFragment.getmBookcasePresenter().cancelEdit();
invalidateOptionsMenu();
cancelEdit();
return;
}
if (System.currentTimeMillis() - APPCONST.exitTime > APPCONST.exitConfirmTime) {
@ -311,10 +322,10 @@ public class MainActivity extends BaseActivity {
BookGroup bookGroup = BookGroupService.getInstance().getGroupById(curBookGroupId);
if (bookGroup == null) {
groupName = "";
}else {
} else {
groupName = bookGroup.getName();
}
if (binding.viewPagerMain.getCurrentItem() == 0){
if (binding.viewPagerMain.getCurrentItem() == 0) {
getSupportActionBar().setSubtitle(groupName);
}
// MyApplication.checkVersionByServer(this);
@ -342,21 +353,21 @@ public class MainActivity extends BaseActivity {
String[] string = result.split("#", 2);
if (string.length == 2) {
SharedBook sharedBook = GsonExtensionsKt.getGSON().fromJson(string[1], SharedBook.class);
if (sharedBook != null && !StringHelper.isEmpty(sharedBook.getChapterUrl())){
if (sharedBook != null && !StringHelper.isEmpty(sharedBook.getChapterUrl())) {
Book book = SharedBook.sharedBookToBook(sharedBook);
Intent intent = new Intent(this, BookDetailedActivity.class);
intent.putExtra(APPCONST.BOOK, book);
startActivity(intent);
}else {
} else {
ToastUtils.showError("书籍加载失败");
}
}else {
} else {
try {
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse(result);
intent.setData(uri);
startActivity(intent);
}catch (Exception e){
} catch (Exception e) {
ToastUtils.showError(e.getLocalizedMessage());
}
}
@ -449,7 +460,7 @@ public class MainActivity extends BaseActivity {
}
}
private void goPrivateBookcase(){
private void goPrivateBookcase() {
MyAlertDialog.showPrivateVerifyDia(this, needGoTo -> {
if (needGoTo) showPrivateBooks();
});
@ -458,7 +469,7 @@ public class MainActivity extends BaseActivity {
/**
* 显示私密书架
*/
private void showPrivateBooks(){
private void showPrivateBooks() {
BookGroup bookGroup = BookGroupService.getInstance().
getGroupById(SharedPreUtils.getInstance().getString("privateGroupId"));
groupName = bookGroup.getName();
@ -471,6 +482,32 @@ public class MainActivity extends BaseActivity {
mBookcaseFragment.onResume();
}
/**
* 取消编辑状态
*/
private void cancelEdit() {
mBookcaseFragment.getmBookcasePresenter().cancelEdit();
invalidateOptionsMenu();
initMenuAnim();
binding.bottomNavigationView.setVisibility(View.VISIBLE);
binding.bottomNavigationView.startAnimation(mBottomInAnim);
}
//初始化菜单动画
public void initMenuAnim() {
if (mBottomInAnim != null) return;
mBottomInAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_in);
mBottomOutAnim = AnimationUtils.loadAnimation(this, R.anim.slide_bottom_out);
}
public Animation getmBottomInAnim() {
return mBottomInAnim;
}
public Animation getmBottomOutAnim() {
return mBottomOutAnim;
}
public interface OnGroupChangeListener {
void onChange();
}

@ -125,8 +125,6 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
private boolean isCollected = true;//是否在书架中
private boolean isPrev;//是否向前翻页
private boolean autoPage = false;//是否自动翻页
private boolean loadFinish = false;
@ -207,11 +205,9 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
mPageLoader.skipToChapter(chapterPos);
mPageLoader.skipToPage(pagePos);
} catch (Exception e) {
ToastUtils.showError("章节跳转失败,请截图联系作者。\n" +
e.getMessage());
//ToastUtils.showError("章节跳转失败,请截图联系作者。\n" + e.getMessage());
e.printStackTrace();
}
binding.pbLoading.setVisibility(View.GONE);
break;
case 3:
break;
@ -227,7 +223,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
break;
case 6:
mPageLoader.openChapter();
if (isPrev) {//判断是否向前翻页打开章节,如果是则打开自己后跳转到最后一页,否则不跳转
if (mPageLoader.isPrev()) {//判断是否向前翻页打开章节,如果是则打开自己后跳转到最后一页,否则不跳转
try {//概率性异常(空指针异常)
mPageLoader.skipToPage(mPageLoader.getAllPagePos() - 1);
} catch (Exception e) {
@ -365,12 +361,12 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
@Override
public void prePage() {
isPrev = true;
mPageLoader.setPrev(true);
}
@Override
public void nextPage(boolean hasNextPage) {
isPrev = false;
mPageLoader.setPrev(false);
if (!hasNextPage) {
if (autoPage) {
autoPageStop();
@ -402,30 +398,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
new PageLoader.OnPageChangeListener() {
@Override
public void onChapterChange(int pos) {
lastLoad(pos);
for (int i = 0; i < 5; i++) {
preLoad(pos - 1 + i);
}
mBook.setHistoryChapterId(mChapters.get(pos).getTitle());
MyApplication.getApplication().newThread(() -> {
if (mPageLoader == null) {
return;
}
if (mPageLoader.getPageStatus() == PageLoader.STATUS_LOADING) {
if (!NetworkUtils.isNetWorkAvailable()) {
mHandler.sendMessage(mHandler.obtainMessage(7));
} else {
mHandler.sendMessage(mHandler.obtainMessage(6));
}
}
});
}
@Override
public void requestChapters(List<Chapter> requestChapters) {
/*for (final Chapter chapter : requestChapters){
getChapterContent(chapter, null);
}*/
}
@Override
@ -578,6 +551,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
}
});
}
@Override
protected void processLogic() {
super.processLogic();
@ -738,7 +712,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
if (itemId == R.id.action_change_source) {
mSourceDialog.show();
} else if (itemId == R.id.action_reload) {
isPrev = false;
mPageLoader.setPrev(false);
if (!"本地书籍".equals(mBook.getType())) {
mChapterService.deleteChapterCacheFile(mChapters.get(mPageLoader.getChapterPos()));
}
@ -891,7 +865,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
binding.tvChapterUrl.setText(StringHelper.isEmpty(url) ? curChapter.getId() : url);
binding.readSbChapterProgress.setProgress(mPageLoader.getPagePos());
binding.readSbChapterProgress.setMax(mPageLoader.getAllPagePos() - 1);
binding.readTvPageTip.setText(String.format("%s/%s", binding.readSbChapterProgress.getProgress() + 1 ,binding.readSbChapterProgress.getMax() + 1));
binding.readTvPageTip.setText(String.format("%s/%s", binding.readSbChapterProgress.getProgress() + 1, binding.readSbChapterProgress.getMax() + 1));
}
}
/************************书籍相关******************************/
@ -1087,20 +1061,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
if (hasChangeSource) {
mBookService.matchHistoryChapterPos(mBook, mChapters);
}
getChapterContent(mChapters.get(mBook.getHisttoryChapterNum()), new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
// mChapters.get(mBook.getHisttoryChapterNum()).setContent((String) o);
mChapterService.saveOrUpdateChapter(mChapters.get(mBook.getHisttoryChapterNum()), (String) o);
mHandler.sendMessage(mHandler.obtainMessage(1));
// getAllChapterData();
}
@Override
public void onError(Exception e) {
mHandler.sendMessage(mHandler.obtainMessage(1));
}
});
mHandler.sendMessage(mHandler.obtainMessage(1));
initMenu();
}
}
@ -1113,93 +1074,14 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
* @param pagePos
*/
private void skipToChapterAndPage(final int chapterPos, final int pagePos) {
isPrev = false;
mPageLoader.setPrev(false);
if (StringHelper.isEmpty(mChapters.get(chapterPos).getContent())) {
if ("本地书籍".equals(mBook.getType())) {
ToastUtils.showWarring("该章节无内容!");
return;
}
binding.pbLoading.setVisibility(View.VISIBLE);
getChapterContent(mChapters.get(chapterPos), new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
mChapterService.saveOrUpdateChapter(mChapters.get(chapterPos), (String) o);
mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos));
}
@Override
public void onError(Exception e) {
mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos));
mHandler.sendEmptyMessage(10);
}
});
} else {
mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos));
}
}
/**
* 获取章节内容
*
* @param chapter
* @param resultCallback
*/
private void getChapterContent(final Chapter chapter, ResultCallback resultCallback) {
if (StringHelper.isEmpty(chapter.getBookId())) {
chapter.setId(mBook.getId());
}
if (!StringHelper.isEmpty(chapter.getContent())) {
if (resultCallback != null) {
resultCallback.onFinish(mChapterService.getChapterCatheContent(chapter), 0);
}
} else {
if ("本地书籍".equals(mBook.getType())) {
return;
}
if (resultCallback != null) {
CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, resultCallback);
} else {
CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, new ResultCallback() {
@Override
public void onFinish(final Object o, int code) {
// chapter.setContent((String) o);
mChapterService.saveOrUpdateChapter(chapter, (String) o);
}
@Override
public void onError(Exception e) {
}
});
}
}
}
/**
* 预加载下一章
*/
private void preLoad(int position) {
if (position + 1 < mChapters.size()) {
Chapter chapter = mChapters.get(position + 1);
if (StringHelper.isEmpty(chapter.getContent())) {
mPageLoader.getChapterContent(chapter);
}
}
}
/**
* 预加载上一章
*
* @param position
*/
private void lastLoad(int position) {
if (position > 0) {
Chapter chapter = mChapters.get(position - 1);
if (StringHelper.isEmpty(chapter.getContent())) {
mPageLoader.getChapterContent(chapter);
}
}
mHandler.sendMessage(mHandler.obtainMessage(2, chapterPos, pagePos));
}
/**
@ -1287,7 +1169,7 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
binding.readAutoPageMenu.startAnimation(mBottomOutAnim);
flag = true;
}
if ( binding.readBrightnessEyeMenu.getVisibility() == VISIBLE) {
if (binding.readBrightnessEyeMenu.getVisibility() == VISIBLE) {
binding.readBrightnessEyeMenu.setVisibility(GONE);
binding.readBrightnessEyeMenu.startAnimation(mBottomOutAnim);
flag = true;
@ -1367,9 +1249,19 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
private void initSettingListener() {
binding.readSettingMenu.setOnClickListener(null);
binding.readSettingMenu.setListener(this, new ReadSettingMenu.Callback() {
@Override
public void onRefreshPage() {
mPageLoader.refreshPagePara();
}
@Override
public void onPageModeChange() {
mPageLoader.setPageMode(mSetting.getPageMode());
}
@Override
public void onRefreshUI() {
mHandler.sendEmptyMessage(5);
mPageLoader.refreshUi();
}
@Override
@ -1675,7 +1567,10 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
}
MyApplication.getApplication().newThread(() -> {
for (Chapter chapter : needDownloadChapters) {
getChapterContent(chapter, new ResultCallback() {
if (StringHelper.isEmpty(chapter.getBookId())) {
chapter.setId(mBook.getId());
}
CommonApi.getChapterContent(chapter.getUrl(), mReadCrawler, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
downloadingChapter = chapter.getTitle();
@ -1904,9 +1799,9 @@ public class ReadActivity extends BaseActivity implements ColorPickerDialogListe
*/
public void showAction() {
float x, y;
if (binding.cursorLeft.getX() - binding.cursorRight.getX() > 0){
if (binding.cursorLeft.getX() - binding.cursorRight.getX() > 0) {
x = binding.cursorRight.getX() + (binding.cursorLeft.getX() - binding.cursorRight.getX()) / 2 + ScreenUtils.dpToPx(12);
}else {
} else {
x = binding.cursorLeft.getX() + (binding.cursorRight.getX() - binding.cursorLeft.getX()) / 2 + ScreenUtils.dpToPx(12);
}
if ((binding.cursorLeft.getY() - ScreenUtils.spToPx(mSetting.getReadWordSize()) - ScreenUtils.dpToPx(60)) < 0) {

@ -54,11 +54,7 @@ public class BookcaseFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
if (android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
mBookcasePresenter.getData();
} else {
mBookcasePresenter.init();
}
mBookcasePresenter.init();
}
public LinearLayout getLlNoDataTips() {

@ -100,7 +100,7 @@ public class ReadSettingMenu extends FrameLayout {
//繁简切换
binding.tvSwitchSt.setOnClickListener(v -> {
initSwitchST(true);
callback.onRefreshUI();
callback.onRefreshPage();
});
//字体选择
binding.tvTextFont.setOnClickListener(v -> callback.onFontClick());
@ -195,7 +195,7 @@ public class ReadSettingMenu extends FrameLayout {
}
dialog.dismiss();
SysManager.saveSetting(setting);
callback.onRefreshUI();
callback.onPageModeChange();
}).show();
});
//横屏竖屏切换
@ -344,6 +344,8 @@ public class ReadSettingMenu extends FrameLayout {
}
public interface Callback{
void onRefreshPage();
void onPageModeChange();
void onRefreshUI();
void onStyleChange();
void onTextSizeChange();

@ -16,6 +16,8 @@ import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.EditText;
@ -74,8 +76,6 @@ public class BookcasePresenter implements BasePresenter {
private final BookcaseFragment mBookcaseFragment;
private final ArrayList<Book> mBooks = new ArrayList<>();//书目数组
private ArrayList<BookGroup> mBookGroups = new ArrayList<>();//书籍分组
private CharSequence[] mGroupNames;//书籍分组名称
private BookcaseAdapter mBookcaseAdapter;
private final BookService mBookService;
private final ChapterService mChapterService;
@ -117,7 +117,6 @@ public class BookcasePresenter implements BasePresenter {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE
};
// private ChapterService mChapterService;
@SuppressLint("HandlerLeak")
public final Handler mHandler = new Handler() {
@Override
@ -245,6 +244,7 @@ public class BookcasePresenter implements BasePresenter {
}
ToastUtils.showSuccess("书籍删除成功!");
init();
mBookcaseAdapter.setCheckedAll(false);
}, null);
}else {
DialogCreator.createCommonDialog(mMainActivity, "批量删除/移除书籍",
@ -255,6 +255,7 @@ public class BookcasePresenter implements BasePresenter {
}
ToastUtils.showSuccess("书籍删除成功!");
init();
mBookcaseAdapter.setCheckedAll(false);
}, (dialog, which) -> {
for (Book book : mBookcaseAdapter.getSelectBooks()) {
book.setGroupId("");
@ -262,6 +263,7 @@ public class BookcasePresenter implements BasePresenter {
}
ToastUtils.showSuccess("书籍已从分组中移除!");
init();
mBookcaseAdapter.setCheckedAll(false);
});
}
});
@ -272,6 +274,7 @@ public class BookcasePresenter implements BasePresenter {
@Override
public void change() {
init();
mBookcaseAdapter.setCheckedAll(false);
if (hasOnGroupChangeListener())
ogcl.onChange();
}
@ -288,7 +291,7 @@ public class BookcasePresenter implements BasePresenter {
//获取数据
public void getData() {
init();
if (mSetting.isRefreshWhenStart() || android.os.Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
if (mSetting.isRefreshWhenStart()) {
mHandler.postDelayed(this::initNoReadNum, 500);
}
}
@ -317,7 +320,22 @@ public class BookcasePresenter implements BasePresenter {
setBtnClickable(mBookcaseAdapter.getmCheckedCount() > 0);
});
mBookcaseFragment.getGvBook().setDragModel(-1);
mBookcaseFragment.getGvBook().setTouchClashparent(((MainActivity) (mBookcaseFragment.getActivity())).getViewPagerMain());
mBookcaseFragment.getGvBook().setTouchClashparent(mMainActivity.getViewPagerMain());
mBookcaseFragment.getGvBook().setOnDragSelectListener(new DragSortGridView.OnDragSelectListener() {
@Override
public void onDragSelect(View mirror) {
if (mSetting.getBookcaseStyle() == BookcaseStyle.listMode){
mirror.setBackgroundColor(mMainActivity.getResources().getColor(R.color.colorBackground));
}else {
mirror.setScaleX(1.05f);
}
mirror.setScaleY(1.05f);
}
@Override
public void onPutDown(View itemView) {
}
});
mBookcaseFragment.getGvBook().setAdapter(mBookcaseAdapter);
isBookcaseStyleChange = false;
} else {
@ -375,23 +393,8 @@ public class BookcasePresenter implements BasePresenter {
}
}
//初始化书籍分组
private void initBookGroups(boolean isAdd) {
mBookGroups.clear();
mBookGroups.addAll(mBookGroupService.getAllGroups());
mGroupNames = new CharSequence[isAdd ? mBookGroups.size() + 1 : mBookGroups.size()];
for (int i = 0; i < mBookGroups.size(); i++) {
String groupName = mBookGroups.get(i).getName();
// mGroupNames[i] = groupName.getBytes().length > 20 ? groupName.substring(0, 8) + "···" : groupName;
mGroupNames[i] = groupName;
}
if (isAdd) {
mGroupNames[mBookGroups.size()] = "添加分组";
}
}
//检查书籍更新
private void initNoReadNum() {
public void initNoReadNum() {
errorLoadingBooks.clear();
finishLoadBookCount = 0;
for (Book book : mBooks) {
@ -557,6 +560,8 @@ public class BookcasePresenter implements BasePresenter {
mBookcaseFragment.getGvBook().setDragModel(DragSortGridView.DRAG_BY_LONG_CLICK);
}
mBookcaseFragment.getRlBookEdit().setVisibility(View.VISIBLE);
mMainActivity.initMenuAnim();
mBookcaseFragment.getRlBookEdit().startAnimation(mMainActivity.getmBottomInAnim());
setBtnClickable(false);
changeCheckedAllStatus();
mBookcaseAdapter.notifyDataSetChanged();
@ -571,6 +576,8 @@ public class BookcasePresenter implements BasePresenter {
mBookcaseFragment.getGvBook().setDragModel(-1);
mBookcaseAdapter.setmEditState(false);
mBookcaseFragment.getRlBookEdit().setVisibility(View.GONE);
mMainActivity.initMenuAnim();
mBookcaseFragment.getRlBookEdit().startAnimation(mMainActivity.getmBottomOutAnim());
mBookcaseAdapter.notifyDataSetChanged();
}
}
@ -976,4 +983,5 @@ public class BookcasePresenter implements BasePresenter {
mBookcaseFragment.getmCbSelectAll().setText("全选");
}
}
}

@ -348,5 +348,31 @@ public class StringUtils {
s2 = s2.trim();
return s1.equals(s2);
}
/**
* 取两个文本之间的文本值
* @param text 源文本 比如欲取全文本为 12345
* @param left 文本前面
* @param right 后面文本
* @return 返回 String
*/
public static String getSubString(String text, String left, String right) {
String result = "";
int zLen;
if (left == null || left.isEmpty()) {
zLen = 0;
} else {
zLen = text.indexOf(left);
if (zLen > -1) {
zLen += left.length();
} else {
zLen = 0;
}
}
int yLen = text.indexOf(right, zLen);
if (yLen < 0 || right == null || right.isEmpty()) {
yLen = text.length();
}
result = text.substring(zLen, yLen);
return result;
}
}

@ -1,5 +1,7 @@
package xyz.fycz.myreader.webapi;
import android.util.Log;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
@ -18,6 +20,7 @@ import xyz.fycz.myreader.webapi.crawler.base.BookInfoCrawler;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
import xyz.fycz.myreader.webapi.crawler.read.FYReadCrawler;
import xyz.fycz.myreader.webapi.crawler.read.TianLaiReadCrawler;
import xyz.fycz.myreader.webapi.crawler.read.YanQingLouReadCrawler;
import java.io.IOException;
import java.util.List;
@ -91,7 +94,14 @@ public class CommonApi extends BaseApi {
getCommonReturnHtmlStringApi(url, null, charset, true, new ResultCallback() {
@Override
public void onFinish(Object o, int code) {
callback.onFinish(rc.getContentFormHtml((String) o), 0);
String html = (String) o;
String content = rc.getContentFormHtml(html);
if (rc instanceof YanQingLouReadCrawler && content.contains("正在加载")){
YanQingLouReadCrawler yrc = (YanQingLouReadCrawler) rc;
yrc.getAjaxContent(html, this);
}else {
callback.onFinish(content, 0);
}
}
@Override

@ -1,10 +1,6 @@
package xyz.fycz.myreader.webapi.callback;
/**
* Created by zhao on 2016/10/25.
*/
public interface ResultCallback {
void onFinish(Object o, int code);

@ -2,24 +2,33 @@ package xyz.fycz.myreader.webapi.crawler.read;
import android.text.Html;
import org.json.JSONException;
import org.json.JSONObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import okhttp3.MediaType;
import okhttp3.RequestBody;
import xyz.fycz.myreader.entity.SearchBookBean;
import xyz.fycz.myreader.enums.BookSource;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.model.mulvalmap.ConcurrentMultiValueMap;
import xyz.fycz.myreader.util.utils.OkHttpUtils;
import xyz.fycz.myreader.util.utils.StringUtils;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
public class YanQingLouReadCrawler implements ReadCrawler {
public static final String NAME_SPACE = "http://www.yanqinglou.com";
public static final String NOVEL_SEARCH = "http://www.yanqinglou.com/Home/Search,action=search&q={key}";
public static final String AJAX_CONTENT = "http://www.yanqinglou.com/home/index/ajaxchapter";
public static final String CHARSET = "UTF-8";
public static final String SEARCH_CHARSET = "UTF-8";
@ -48,6 +57,19 @@ public class YanQingLouReadCrawler implements ReadCrawler {
return SEARCH_CHARSET;
}
/*
var preview_page = "/lishi/220987/60.html";
var next_page = "/lishi/220987/62.html";
var index_page = "/lishi/220987/";
var article_id = "220987";
var chapter_id = "61";
var nextcid = "62";
var prevcid = "60";
var articlename = "临高启明";
var chaptername = "第十五节 遇伏";
var hash = "38e338d183600e17";
var localpre = "www.yanqinglou.com";
*/
/**
* 从html中获取章节正文
*
@ -61,13 +83,45 @@ public class YanQingLouReadCrawler implements ReadCrawler {
String content = Html.fromHtml(divContent.html()).toString();
char c = 160;
String spaec = "" + c;
content = content.replace(spaec, " ");
content = content.replace(spaec, " ")
.replaceAll("您可以.*最新章节!", "")
.replaceAll("转码页面.*com/", "");
return content;
} else {
return "";
}
}
/*
id: 220987
eKey: fe9535a08b53e929
cid: 62
basecid: 62
*/
public void getAjaxContent(String html, ResultCallback callback){
String id = StringUtils.getSubString(html, "var article_id = \"", "\";");
String eKey = StringUtils.getSubString(html, "var hash = \"", "\";");
String cid = StringUtils.getSubString(html, "var chapter_id = \"", "\";");
String body = "id=" + id + "&eKey=" + eKey + "&cid=" + cid + "&basecid=" + cid;
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody requestBody = RequestBody.create(mediaType, body);
try {
String jsonStr = OkHttpUtils.getHtml(AJAX_CONTENT, requestBody, CHARSET);
JSONObject json = new JSONObject(jsonStr);
String content = json.getJSONObject("info").getString("content");
content = Html.fromHtml(content).toString();
char c = 160;
String spaec = "" + c;
content = content.replace(spaec, " ")
.replaceAll("您可以.*最新章节!", "")
.replaceAll("转码页面.*com/", "");
callback.onFinish(content, 0);
} catch (IOException | JSONException e) {
e.printStackTrace();
callback.onError(e);
}
}
/**
* 从html中获取章节列表
*
@ -122,7 +176,7 @@ public class YanQingLouReadCrawler implements ReadCrawler {
book.setType(divBook.getElementsByClass("author").get(1).text().replace("分类:", ""));
book.setNewestChapterTitle(as.get(3).text().replace("最近更新>>", ""));
book.setDesc(divBook.getElementsByClass("update").first().text().replace("简介:", ""));
book.setImgUrl(divBook.getElementsByTag("img").attr("src"));
book.setImgUrl(NAME_SPACE + divBook.getElementsByTag("img").attr("src"));
book.setChapterUrl(NAME_SPACE + as.get(0).attr("href"));
book.setSource(BookSource.yanqinglou.toString());
SearchBookBean sbb = new SearchBookBean(book.getName(), book.getAuthor());

@ -398,9 +398,4 @@ public class LocalPageLoader extends PageLoader {
return chapter.getEnd() > 0 || ChapterService.isChapterCached(mCollBook.getId(), chapter.getTitle());
}
@Override
public void getChapterContent(Chapter chapter) {
}
}

@ -1,6 +1,11 @@
package xyz.fycz.myreader.widget.page;
import android.util.Log;
import xyz.fycz.myreader.application.MyApplication;
import xyz.fycz.myreader.util.StringHelper;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.webapi.callback.ResultCallback;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.entity.Setting;
@ -72,22 +77,6 @@ public class NetPageLoader extends PageLoader {
+ File.separator + chapter.getTitle() + FileUtils.SUFFIX_FY);
if (!file.exists()) return null;
BufferedReader br = new BufferedReader(new FileReader(file));
/*try {
if (StringHelper.isEmpty(br.readLine())){
getChapterContent(chapter);
assert chapter.getContent() != null;
//保证chapter更新完毕,暂时先这么用着
for (int i = 0; i < 5; i++) {
if (!StringHelper.isEmpty(chapter.getContent())){
break;
}
Thread.sleep(1000);
}
return br;
}
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}*/
return br;
}
@ -135,12 +124,12 @@ public class NetPageLoader extends PageLoader {
}
/**
* 加载当前页的前面个章节
* 加载当前页的前面个章节
*/
private void loadPrevChapter() {
if (mPageChangeListener != null) {
int end = mCurChapterPos;
int begin = end - 2;
int begin = end - 1;
if (begin < 0) {
begin = 0;
}
@ -176,14 +165,14 @@ public class NetPageLoader extends PageLoader {
}
/**
* 加载当前页的后个章节
* 加载当前页的后个章节
*/
private void loadNextChapter() {
if (mPageChangeListener != null) {
// 提示加载后
// 提示加载后
int begin = mCurChapterPos + 1;
int end = begin + 1;
int end = begin + 3;
// 判断是否大于最后一章
if (begin >= mChapterList.size()) {
@ -220,7 +209,9 @@ public class NetPageLoader extends PageLoader {
}
if (!chapters.isEmpty()) {
mPageChangeListener.requestChapters(chapters);
for (Chapter chapter : chapters) {
getChapterContent(chapter);
}
}
}
@ -242,10 +233,21 @@ public class NetPageLoader extends PageLoader {
public void onFinish(final Object o, int code) {
// chapter.setContent((String) o);
mChapterService.saveOrUpdateChapter(chapter, (String) o);
if (getPageStatus() == PageLoader.STATUS_LOADING) {
MyApplication.runOnUiThread(() -> {
if (isPrev) {
openChapterInLastPage();
} else {
openChapter();
}
});
}
}
@Override
public void onError(Exception e) {
ToastUtils.showError("章节加载失败\n" + e.getLocalizedMessage());
e.printStackTrace();
}
});

@ -27,6 +27,7 @@ import xyz.fycz.myreader.enums.Language;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.model.audio.ReadAloudService;
import xyz.fycz.myreader.util.IOUtils;
import xyz.fycz.myreader.util.ToastUtils;
@ -150,10 +151,10 @@ public abstract class PageLoader {
private int mBatteryLevel;
//当前页面的背景
private int mBgColor;
//繁简体
private Language language;
// 当前章
protected int mCurChapterPos = 0;
//是否向前翻页
protected boolean isPrev;
//上一章的记录
private int mLastChapterPos = 0;
private int readTextLength; //已读字符数
@ -212,9 +213,6 @@ public abstract class PageLoader {
mPageMode = mSettingManager.getPageMode();
//获取字体
getFont(mSettingManager.getFont());
//获取繁简体
language = mSettingManager.getLanguage();
// mPageStyle = mSettingManager.getPageStyle();
indent = StringUtils.repeat(StringUtils.halfToFull(" "), mSettingManager.getIntent());
initBgBitmap();
@ -319,6 +317,7 @@ public abstract class PageLoader {
* @return
*/
public boolean skipPreChapter() {
isPrev = false;
if (!hasPrevChapter()) {
return false;
}
@ -339,6 +338,7 @@ public abstract class PageLoader {
* @return
*/
public boolean skipNextChapter() {
isPrev = false;
if (!hasNextChapter()) {
return false;
}
@ -359,6 +359,7 @@ public abstract class PageLoader {
* @param pos: 0 开始
*/
public void skipToChapter(int pos) {
isPrev = false;
// 设置参数
mCurChapterPos = pos;
@ -540,7 +541,7 @@ public abstract class PageLoader {
refreshPagePara();
}
private void refreshPagePara() {
public void refreshPagePara() {
// 取消缓存
mPreChapter = null;
mNextChapter = null;
@ -597,7 +598,7 @@ public abstract class PageLoader {
*/
public void refreshChapter(Chapter chapter) {
chapter.setContent(null);
getChapterContent(chapter);
ChapterService.getInstance().deleteChapterCacheFile(chapter);
openChapter();
}
@ -755,6 +756,18 @@ public abstract class PageLoader {
mPageView.drawCurPage(false);
}
/**
* 解析章节并跳转到最后一页
*/
protected void openChapterInLastPage() {
if (parseCurChapter()) {
mCurPage = getCurPage(getAllPagePos() - 1);
} else {
mCurPage = new TxtPage();
}
mPageView.drawCurPage(false);
}
public void chapterError() {
//加载错误
mStatus = STATUS_ERROR;
@ -839,12 +852,6 @@ public abstract class PageLoader {
*/
public abstract boolean hasChapterData(Chapter chapter);
/**
*
*/
public abstract void getChapterContent(Chapter chapter);
/***********************************default method***********************************************/
void drawPage(Bitmap bitmap, boolean isUpdate) {
@ -1985,6 +1992,14 @@ public abstract class PageLoader {
return null;
}
public boolean isPrev() {
return isPrev;
}
public void setPrev(boolean prev) {
isPrev = prev;
}
/*****************************************interface*****************************************/
public interface OnPageChangeListener {
@ -1995,13 +2010,6 @@ public abstract class PageLoader {
*/
void onChapterChange(int pos);
/**
* 作用请求加载章节内容
*
* @param requestChapters:需要下载的章节列表
*/
void requestChapters(List<Chapter> requestChapters);
/**
* 作用章节目录加载完成时候回调
*

@ -6,15 +6,15 @@
android:viewportHeight="24">
<path
android:fillColor="#595757"
android:fillColor="#FFFFFF"
android:pathData="M 11.221 5.832 L 11.221 6.608 L 11.221 11.094 L 9.57 11.094 L 9.57 12.647 L 11.221 12.647 L 11.221 17.909 L 11.229 17.909 L 11.229 18.686 L 13.939 18.686 L 13.939 17.132 L 12.773 17.132 L 12.773 6.608 L 13.939 6.608 L 13.939 5.055 L 11.221 5.055 Z" />
<path
android:fillColor="#595757"
android:fillColor="#FFFFFF"
android:pathData="M6.707,7.27H4.414C3.396,7.27,2.6,7.963,2.6,8.848v6.044c0,0.885,0.797,1.578,1.814,1.578h2.293 c1.019,0,1.816-0.693,1.816-1.578V8.848C8.523,7.963,7.726,7.27,6.707,7.27z M6.707,14.917H4.414c-0.131,0-0.215-0.041-0.246-0.041 c-0.01,0-0.014,0.003-0.015,0.012L4.137,8.913C4.15,8.895,4.24,8.823,4.414,8.823h2.293c0.17,0,0.26,0.067,0.263,0.029l0.017,5.975 C6.973,14.845,6.881,14.917,6.707,14.917z" />
<path
android:fillColor="#595757"
android:fillColor="#FFFFFF"
android:pathData="M16.91,8.793h2.805c0.86,0,1.561-0.699,1.561-1.559V4.429c0-0.86-0.7-1.559-1.561-1.559H16.91 c-0.859,0-1.559,0.699-1.559,1.559v2.805C15.352,8.094,16.051,8.793,16.91,8.793z M16.91,4.423l2.812,0.006L19.717,7.24 c0,0,0,0-0.002,0l-2.81-0.006L16.91,4.423z" />
<path
android:fillColor="#595757"
android:fillColor="#FFFFFF"
android:pathData="M19.84,14.947h-2.805c-0.859,0-1.558,0.699-1.558,1.559v2.805c0,0.86,0.698,1.559,1.558,1.559h2.805 c0.861,0,1.561-0.699,1.561-1.559v-2.805C21.4,15.646,20.701,14.947,19.84,14.947z M19.848,19.312c0,0-0.004,0.005-0.008,0.005 l-2.809-0.006l0.004-2.811l2.813,0.006V19.312z" />
</vector>

@ -1,148 +1,147 @@
<com.scwang.smartrefresh.layout.SmartRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/srl_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground"
tools:context="xyz.fycz.myreader.ui.fragment.BookcaseFragment">
<com.scwang.smartrefresh.layout.SmartRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/srl_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBackground"
tools:context="xyz.fycz.myreader.ui.fragment.BookcaseFragment">
<com.scwang.smartrefresh.header.MaterialHeader
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:scrollbars="none">
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="none">
<LinearLayout
android:id="@+id/ll_no_data_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
android:visibility="gone">
android:id="@+id/ll_no_data_tips"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
android:visibility="gone">
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
app:tint="@color/textSecondary"
app:srcCompat="@drawable/ic_vector_add_bookcase"/>
android:layout_width="100dp"
android:layout_height="100dp"
app:srcCompat="@drawable/ic_vector_add_bookcase"
app:tint="@color/textSecondary" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="当前无任何书籍,点击添加"
android:textColor="@color/textSecondary"
android:textSize="16sp"/>
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="当前无任何书籍,点击添加"
android:textColor="@color/textSecondary"
android:textSize="16sp" />
</LinearLayout>
<xyz.fycz.myreader.widget.custom.DragSortGridView
android:id="@+id/gv_book"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:columnWidth="100dp"
android:horizontalSpacing="10dp"
android:listSelector="@android:color/transparent"
android:numColumns="auto_fit"
android:scrollbars="none"
android:padding="5dp"
android:verticalSpacing="10dp">
</xyz.fycz.myreader.widget.custom.DragSortGridView>
android:id="@+id/gv_book"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@+id/rl_book_edit"
android:layout_alignParentTop="true"
android:columnWidth="100dp"
android:gravity="center"
android:horizontalSpacing="10dp"
android:listSelector="@android:color/transparent"
android:numColumns="auto_fit"
android:scrollbars="none"
android:verticalSpacing="10dp" />
<RelativeLayout
android:id="@+id/rl_download_tip"
android:layout_width="match_parent"
android:layout_height="39dp"
android:layout_alignParentBottom="true"
android:background="@color/colorForeground"
android:visibility="gone">
android:id="@+id/rl_download_tip"
android:layout_width="match_parent"
android:layout_height="39dp"
android:layout_alignParentBottom="true"
android:background="@color/colorForeground"
android:visibility="gone">
<ProgressBar
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_alignParentTop="true"
style="?android:attr/progressBarStyleHorizontal"
android:id="@+id/pb_download"
android:max="100"
/>
android:id="@+id/pb_download"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="4dp"
android:layout_alignParentTop="true"
android:max="100" />
<TextView
android:id="@+id/tv_download_tip"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/textSecondary"
android:text="正在初始化..."
android:gravity="center_vertical|start"
android:maxLines="1"
android:textSize="14sp"
android:paddingStart="15dp"/>
android:id="@+id/tv_download_tip"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center_vertical|start"
android:maxLines="1"
android:paddingStart="15dp"
android:text="正在初始化..."
android:textColor="@color/textSecondary"
android:textSize="14sp" />
<TextView
android:id="@+id/tv_stop_download"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textColor="@color/colorAccent"
android:textSize="14sp"
android:text="@string/stop_download_tip"
android:layout_alignParentEnd="true"
android:gravity="center_vertical"
android:paddingEnd="15dp"
android:paddingStart="15dp"
android:visibility="gone"/>
android:id="@+id/tv_stop_download"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:gravity="center_vertical"
android:paddingStart="15dp"
android:paddingEnd="15dp"
android:text="@string/stop_download_tip"
android:textColor="@color/colorAccent"
android:textSize="14sp"
android:visibility="gone" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/rl_book_edit"
android:layout_width="match_parent"
android:layout_height="52dp"
android:paddingRight="10dp"
android:layout_alignParentBottom="true"
android:background="@color/colorForeground"
android:gravity="center_vertical"
android:visibility="gone">
android:id="@+id/rl_book_edit"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_alignParentBottom="true"
android:background="@color/colorForeground"
android:gravity="center_vertical"
android:paddingEnd="10dp"
android:visibility="gone">
<CheckBox
android:id="@+id/book_selected_all"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:text="全选"
android:textSize="15dp"
android:textColor="@color/textSecondary"
android:theme="@style/MyCheckBox" />
android:id="@+id/book_selected_all"
android:layout_width="120dp"
android:layout_height="40dp"
android:layout_centerVertical="true"
android:layout_marginStart="15dp"
android:text="全选"
android:textColor="@color/textSecondary"
android:textSize="15dp"
android:theme="@style/MyCheckBox" />
<Button
android:id="@+id/book_add_group"
android:layout_width="90dp"
android:layout_height="35dp"
android:minWidth="110dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:enabled="false"
android:clickable="false"
android:background="@drawable/selector_btn_add"
android:textColor="@color/selector_btn_file_add"
android:text="加入分组" />
android:id="@+id/book_add_group"
android:layout_width="90dp"
android:layout_height="35dp"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:background="@drawable/selector_btn_add"
android:clickable="false"
android:enabled="false"
android:minWidth="110dp"
android:text="加入分组"
android:textColor="@color/selector_btn_file_add" />
<Button
android:id="@+id/book_btn_delete"
android:layout_width="90dp"
android:layout_height="35dp"
android:layout_centerVertical="true"
android:layout_marginRight="15dp"
android:enabled="false"
android:clickable="false"
android:background="@drawable/selector_btn_add"
android:textColor="@color/selector_btn_file_add"
android:layout_toLeftOf="@id/book_add_group"
android:text="删除/移除"/>
android:id="@+id/book_btn_delete"
android:layout_width="90dp"
android:layout_height="35dp"
android:layout_centerVertical="true"
android:layout_marginEnd="15dp"
android:layout_toLeftOf="@id/book_add_group"
android:background="@drawable/selector_btn_add"
android:clickable="false"
android:enabled="false"
android:text="删除/移除"
android:textColor="@color/selector_btn_file_add" />
</RelativeLayout>
</RelativeLayout>
</com.scwang.smartrefresh.layout.SmartRefreshLayout>

@ -1,118 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/rl_book_item"
xmlns:android="http://schemas.android.com/apk/res/android"
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/rl_book_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp">
<LinearLayout
android:id="@+id/ll_book_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical">
android:orientation="horizontal"
android:padding="5dp">
<LinearLayout
android:id="@+id/ll_book_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="5dp">
<CheckBox
android:id="@+id/cb_book_select"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:enabled="true"
android:clickable="false"
android:focusable="true"
android:paddingEnd="2dp"
android:theme="@style/MyCheckBox"
android:visibility="gone"/>
android:id="@+id/cb_book_select"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:clickable="false"
android:enabled="true"
android:focusable="true"
android:paddingEnd="2dp"
android:theme="@style/MyCheckBox"
android:visibility="gone" />
<xyz.fycz.myreader.widget.CoverImageView
android:id="@+id/iv_book_img"
android:layout_width="64dp"
android:layout_height="88dp"
android:scaleType="fitXY"
app:srcCompat="@mipmap/default_cover" />
<LinearLayout android:id="@+id/ll_book_read"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
android:id="@+id/iv_book_img"
android:layout_width="64dp"
android:layout_height="88dp"
android:scaleType="fitXY"
app:srcCompat="@mipmap/default_cover" />
<LinearLayout
android:id="@+id/ll_book_read"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tv_book_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:padding="4dp"
android:text="bookname"
android:textSize="16dp"
android:textColor="@color/textPrimary"/>
android:id="@+id/tv_book_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:padding="4dp"
android:text="bookname"
android:textColor="@color/textPrimary"
android:textSize="16dp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="3dp"
app:tint="@color/textSecondary"
app:srcCompat="@drawable/ic_author"/>
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="3dp"
app:srcCompat="@drawable/ic_author"
app:tint="@color/textSecondary" />
<TextView
android:id="@+id/tv_book_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="辰东"
android:textSize="12dp"
android:textColor="@color/textSecondary"/>
</LinearLayout>
<LinearLayout
android:id="@+id/tv_book_author"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
android:maxLines="1"
android:text="辰东"
android:textColor="@color/textSecondary"
android:textSize="12dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:tint="@color/textSecondary"
android:padding="3dp"
app:srcCompat="@drawable/ic_history"/>
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="3dp"
app:srcCompat="@drawable/ic_history"
app:tint="@color/textSecondary" />
<TextView
android:id="@+id/tv_book_history_chapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:text="第1章 xxxxxxxx"
android:textSize="12dp"
android:textColor="@color/textSecondary"/>
</LinearLayout>
<LinearLayout
android:id="@+id/tv_book_history_chapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
android:ellipsize="end"
android:maxLines="1"
android:text="第1章 xxxxxxxx"
android:textColor="@color/textSecondary"
android:textSize="12dp" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="20dp"
android:layout_height="20dp"
app:tint="@color/textSecondary"
android:padding="3dp"
app:srcCompat="@drawable/ic_book_last"/>
android:layout_width="20dp"
android:layout_height="20dp"
android:padding="3dp"
app:srcCompat="@drawable/ic_book_last"
app:tint="@color/textSecondary" />
<TextView
android:id="@+id/tv_book_newest_chapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:ellipsize="end"
android:text="第999章 xxxxxxxx"
android:textSize="12dp"
android:textColor="@color/textSecondary"/>
android:id="@+id/tv_book_newest_chapter"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:text="第999章 xxxxxxxx"
android:textColor="@color/textSecondary"
android:textSize="12dp" />
</LinearLayout>
</LinearLayout>
@ -122,28 +128,27 @@
<xyz.fycz.myreader.widget.BadgeView
android:id="@+id/tv_no_read_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_margin="5dp"
android:includeFontPadding="false"
android:layout_marginRight="10dp"/>
android:id="@+id/tv_no_read_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_margin="5dp"
android:layout_marginRight="10dp"
android:includeFontPadding="false" />
<ProgressBar
android:id="@+id/pb_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:visibility="gone"
android:layout_alignParentRight="true"
style="?android:attr/progressBarStyleSmall"
/>
<View
android:layout_width="fill_parent"
android:layout_height="0.5dp"
android:layout_alignParentBottom="true"
android:background="@color/sys_window_back"/>
android:id="@+id/pb_loading"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="10dp"
android:visibility="gone" />
<View
android:layout_width="fill_parent"
android:layout_height="0.5dp"
android:layout_alignParentBottom="true"
android:background="@color/sys_window_back" />
</RelativeLayout>

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="100dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
@ -50,7 +50,7 @@
android:layout_marginTop="15dp"
android:layout_marginEnd="28dp"
android:visibility="gone"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
style="?android:attr/progressBarStyleSmall"
/>

@ -1,19 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2016 JustWayward Team
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/rl_empty_view"
android:layout_width="match_parent"

@ -4,10 +4,15 @@
android:layout_height="match_parent">
<item
android:id="@+id/action_finish"
android:title="完成"
android:title="@string/finish"
app:showAsAction="always"
android:visible="false"/>
<item
android:visible="false"
android:id="@+id/action_refresh"
android:icon="@drawable/ic_refresh"
android:title="@string/refresh_books"
app:showAsAction="never"/>
<group android:id="@+id/bookcase_menu">
<item
@ -20,6 +25,7 @@
android:icon="@drawable/ic_change"
android:title="@string/menu_change_group"
app:showAsAction="always"/>
<item
android:id="@+id/action_edit"
android:icon="@drawable/ic_arrange"

@ -0,0 +1,17 @@
<?xml version ="1.0" encoding ="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<item
android:id="@+id/action_share"
android:icon="@drawable/ic_share"
android:title="@string/menu_share"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_group_setting"
android:title="@string/menu_group_setting"
android:icon="@drawable/ic_group"
app:showAsAction="never" />
</menu>

@ -335,6 +335,8 @@
<string name="delete_ban_rule">删除禁用规则</string>
<string name="import_rule">导入规则</string>
<string name="help">帮助</string>
<string name="refresh_books">更新目录</string>
<string name="finish">完成</string>
<string-array name="reset_screen_time">
<item>常亮</item>

@ -1,2 +1,2 @@
#Mon Feb 01 19:33:27 CST 2021
#Wed Feb 03 13:23:18 CST 2021
VERSION_CODE=181

Loading…
Cancel
Save