新增分组管理界面

master
fengyuecanzhu 3 years ago
parent 53e21bc22e
commit 3ddcaaff76
  1. 4
      .idea/assetWizardSettings.xml
  2. 7
      .idea/misc.xml
  3. 1
      app/src/main/AndroidManifest.xml
  4. 4
      app/src/main/java/xyz/fycz/myreader/application/SysManager.java
  5. 86
      app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java
  6. 7
      app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java
  7. 3
      app/src/main/java/xyz/fycz/myreader/common/APPCONST.java
  8. 9
      app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java
  9. 111
      app/src/main/java/xyz/fycz/myreader/ui/activity/GroupManagerActivity.kt
  10. 7
      app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java
  11. 126
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookGroupAdapter.kt
  12. 37
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookSourceAdapter.java
  13. 47
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java
  14. 17
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDetailedAdapter.java
  15. 22
      app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java
  16. 6
      app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/IItemTouchHelperViewHolder.java
  17. 15
      app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/ItemTouchCallback.java
  18. 4
      app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookSourceHolder.java
  19. 4
      app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java
  20. 12
      app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java
  21. 14
      app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java
  22. 18
      app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java
  23. 31
      app/src/main/res/anim/anim_recycle_item.xml
  24. 12
      app/src/main/res/drawable/ic_cross.xml
  25. 12
      app/src/main/res/drawable/ic_plus.xml
  26. 60
      app/src/main/res/layout/activity_group_manager.xml
  27. 2
      app/src/main/res/layout/fragment_private_bookcase.xml
  28. 42
      app/src/main/res/layout/item_group.xml
  29. 3
      app/src/main/res/values/strings.xml

@ -14,8 +14,8 @@
<option name="values">
<map>
<entry key="assetSourceType" value="FILE" />
<entry key="outputName" value="ic_re_seg" />
<entry key="sourceFile" value="F:\SVG图标\段落说明.svg" />
<entry key="outputName" value="ic_plus" />
<entry key="sourceFile" value="F:\SVG图标\.svg" />
</map>
</option>
</PersistentState>

@ -6,9 +6,16 @@
<entry key="..\:/android/FYReader/app/src/main/res/drawable/ic_re_seg.xml" value="0.1962962962962963" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_about.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_donate.xml" value="0.536" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_group_manager.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_manage_group.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/activity_more_setting.xml" value="0.264" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fingerprint_dialog.xml" value="0.20425724637681159" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_find_book_2.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_private_bookcase.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/fragment_webdav_setting.xml" value="0.4" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/item_book_source.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/item_group.xml" value="0.4" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/item_local_source.xml" value="0.21195652173913043" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/layout_about_content.xml" value="0.12132725430597771" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/listview_search_book_item.xml" value="0.22010869565217392" />
<entry key="..\:/android/FYReader/app/src/main/res/layout/view_file_picker.xml" value="0.12132725430597771" />

@ -119,6 +119,7 @@
<activity android:name=".ui.activity.SourceLoginActivity" />
<activity android:name=".ui.activity.ReadRecordActivity" />
<activity android:name=".ui.activity.FindBookActivity" />
<activity android:name=".ui.activity.GroupManagerActivity" />
<receiver android:name=".util.notification.NotificationClickReceiver" />
<receiver android:name=".ui.presenter.BookcasePresenter$cancelDownloadReceiver" />

@ -7,6 +7,7 @@ import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.entity.Setting;
import xyz.fycz.myreader.enums.BookcaseStyle;
import xyz.fycz.myreader.enums.LocalBookSource;
import xyz.fycz.myreader.greendao.service.BookGroupService;
import xyz.fycz.myreader.util.CacheHelper;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
@ -98,6 +99,9 @@ public class SysManager {
setting.setSharedLayout(true);
Log.d("SettingVersion", "" + 10);
case 11:
if (BookGroupService.getInstance().countBookGroup() > 0) {
SharedPreUtils.getInstance().putBoolean("openGroup", true);
}
Log.d("SettingVersion", "" + 11);
case 12:
Log.d("SettingVersion", "" + 12);

@ -49,23 +49,23 @@ public abstract class BaseListAdapter<T> extends RecyclerView.Adapter<RecyclerVi
iHolder.onBind(holder, getItem(position), position);
//设置点击事件
holder.itemView.setOnClickListener((v)->{
if (mClickListener != null){
mClickListener.onItemClick(v,position);
holder.itemView.setOnClickListener((v) -> {
if (mClickListener != null) {
mClickListener.onItemClick(v, position);
}
//adapter监听点击事件
iHolder.onClick();
onItemClick(v,position);
onItemClick(v, position);
});
//设置长点击事件
holder.itemView.setOnLongClickListener(
(v) -> {
boolean isClicked = false;
if (mLongClickListener != null){
isClicked = mLongClickListener.onItemLongClick(v,position);
if (mLongClickListener != null) {
isClicked = mLongClickListener.onItemLongClick(v, position);
}
//Adapter监听长点击事件
onItemLongClick(v,position);
onItemLongClick(v, position);
return isClicked;
}
);
@ -81,10 +81,10 @@ public abstract class BaseListAdapter<T> extends RecyclerView.Adapter<RecyclerVi
return null;
}
protected void onItemClick(View v, int pos){
protected void onItemClick(View v, int pos) {
}
protected void onItemLongClick(View v, int pos){
protected void onItemLongClick(View v, int pos) {
}
/******************************public area***********************************/
@ -93,71 +93,85 @@ public abstract class BaseListAdapter<T> extends RecyclerView.Adapter<RecyclerVi
this.mClickListener = mListener;
}
public void setOnItemLongClickListener(OnItemLongClickListener mListener){
public void setOnItemLongClickListener(OnItemLongClickListener mListener) {
this.mLongClickListener = mListener;
}
public void addItem(T value){
mList.add(value);
notifyDataSetChanged();
public synchronized void addItem(T value) {
int oldSize = getItemSize();
if (mList.add(value)) {
notifyItemInserted(oldSize);
}
}
public void addItem(int index,T value){
public synchronized void addItem(int index, T value) {
mList.add(index, value);
notifyDataSetChanged();
notifyItemInserted(index);
}
public void addItems(List<T> values){
mList.addAll(values);
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
public synchronized void addItems(List<T> values) {
int oldSize = getItemSize();
if (mList.addAll(values)) {
if (oldSize == 0) {
notifyDataSetChanged();
} else {
notifyItemRangeInserted(oldSize, values.size());
}
});
}
}
public void removeItem(T value){
mList.remove(value);
notifyDataSetChanged();
public synchronized void removeItem(T value) {
int pos = mList.indexOf(value);
if (mList.remove(value)){
notifyItemRemoved(pos);
if (pos != mList.size())
notifyItemRangeChanged(pos, mList.size() - pos);
}
}
public void removeItems(List<T> value){
mList.removeAll(value);
notifyDataSetChanged();
public synchronized void removeItems(List<T> value) {
if (mList.removeAll(value)) {
notifyDataSetChanged();
}
}
public synchronized void swapItem(int oldPos, int newPos){
int size = getItemSize();
if (oldPos >= 0 && oldPos < size && newPos >=0 && newPos < size){
Collections.swap(mList, oldPos, newPos);
notifyItemMoved(oldPos, newPos);
}
}
public T getItem(int position){
public T getItem(int position) {
return mList.get(position);
}
public List<T> getItems(){
public List<T> getItems() {
return Collections.unmodifiableList(mList);
}
public int getItemSize(){
public int getItemSize() {
return mList.size();
}
public void refreshItems(List<T> list){
public synchronized void refreshItems(List<T> list) {
mList.clear();
mList.addAll(list);
notifyDataSetChanged();
}
public void clear(){
public synchronized void clear() {
mList.clear();
notifyDataSetChanged();
}
/***************************inner class area***********************************/
public interface OnItemClickListener{
public interface OnItemClickListener {
void onItemClick(View view, int pos);
}
public interface OnItemLongClickListener{
public interface OnItemLongClickListener {
boolean onItemLongClick(View view, int pos);
}
}

@ -4,6 +4,12 @@ import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import androidx.recyclerview.widget.RecyclerView;
import xyz.fycz.myreader.R;
/**
* @author fengyue
@ -16,7 +22,6 @@ public abstract class ViewHolderImpl<T> implements IViewHolder<T> {
/****************************************************/
protected abstract int getItemLayoutId();
@Override
public View createItemView(ViewGroup parent) {
view = LayoutInflater.from(parent.getContext())

@ -93,6 +93,7 @@ public class APPCONST {
public static final int REQUEST_BOOK_SOURCE = 1011;
public static final int REQUEST_SELECT_COVER = 1012;
public static final int REQUEST_EDIT_BOOK = 1013;
public static final int REQUEST_GROUP_MANAGER = 1014;
public static final int REQUEST_READ = 1;
@ -101,7 +102,7 @@ public class APPCONST {
public static final int SELECT_FILE_CODE = 10000;
//设置版本号
public static final int SETTING_VERSION = 11;
public static final int SETTING_VERSION = 12;
public static final int SOURCE_VERSION = 7;

@ -1,9 +1,12 @@
package xyz.fycz.myreader.greendao.service;
import org.jetbrains.annotations.NotNull;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.greendao.DbManager;
import xyz.fycz.myreader.greendao.entity.BookGroup;
import xyz.fycz.myreader.greendao.gen.BookDao;
import xyz.fycz.myreader.greendao.gen.BookGroupDao;
import xyz.fycz.myreader.util.SharedPreUtils;
import xyz.fycz.myreader.util.help.StringHelper;
@ -96,10 +99,14 @@ public class BookGroupService extends BaseService{
return !StringHelper.isEmpty(curBookGroupId) && curBookGroupId.equals(privateGroupId);
}
private int countBookGroup(){
public int countBookGroup(){
return (int) DbManager.getInstance().getSession().getBookGroupDao()
.queryBuilder()
.count();
}
public void updateGroups(@NotNull List<BookGroup> groups) {
BookGroupDao bookDao = DbManager.getInstance().getSession().getBookGroupDao();
bookDao.insertOrReplaceInTx(groups);
}
}

@ -0,0 +1,111 @@
package xyz.fycz.myreader.ui.activity
import android.app.Activity
import android.os.Bundle
import android.view.View
import androidx.appcompat.widget.Toolbar
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import androidx.recyclerview.widget.ItemTouchHelper
import androidx.recyclerview.widget.LinearLayoutManager
import io.reactivex.Single
import xyz.fycz.myreader.R
import xyz.fycz.myreader.application.App
import xyz.fycz.myreader.application.SysManager
import xyz.fycz.myreader.base.BaseActivity
import xyz.fycz.myreader.databinding.ActivityGroupManagerBinding
import xyz.fycz.myreader.databinding.ItemGroupBinding
import xyz.fycz.myreader.greendao.entity.BookGroup
import xyz.fycz.myreader.ui.adapter.BookGroupAdapter
import xyz.fycz.myreader.ui.adapter.helper.ItemTouchCallback
import xyz.fycz.myreader.ui.dialog.BookGroupDialog
import xyz.fycz.myreader.util.SharedPreUtils
/**
* @author fengyue
* @date 2021/8/30 12:48
*/
class GroupManagerActivity : BaseActivity() {
private lateinit var binding: ActivityGroupManagerBinding
private lateinit var adapter: BookGroupAdapter
private lateinit var groupDialog: BookGroupDialog
private lateinit var itemTouchHelper: ItemTouchHelper
private var openGroup: Boolean = false
override fun bindView() {
binding = ActivityGroupManagerBinding.inflate(layoutInflater)
setContentView(binding.root)
}
override fun setUpToolbar(toolbar: Toolbar?) {
super.setUpToolbar(toolbar)
setStatusBarColor(R.color.colorPrimary, true)
supportActionBar?.title = getString(R.string.manage_book_group)
}
override fun initData(savedInstanceState: Bundle?) {
super.initData(savedInstanceState)
groupDialog = BookGroupDialog(this)
groupDialog.initBookGroups(false)
openGroup = SharedPreUtils.getInstance().getBoolean("openGroup")
}
override fun initWidget() {
super.initWidget()
binding.scBookGroup.isChecked = openGroup
binding.recyclerView.visibility = if (openGroup) View.VISIBLE else View.GONE
adapter = BookGroupAdapter(this, { itemTouchHelper.startDrag(it) }, groupDialog).apply {
setItems(groupDialog.getmBookGroups())
addFooterView {
ItemGroupBinding.inflate(inflater, it, false).apply {
ivIcon.setImageDrawable(
ContextCompat.getDrawable(
this@GroupManagerActivity,
R.drawable.ic_plus
)
)
ivIcon.setColorFilter(resources.getColor(R.color.colorAccent))
tvGroupName.text = "添加分组"
ivMove.visibility = View.GONE
root.setOnClickListener {
groupDialog.showAddOrRenameGroupDia(false, true, 0,
object : BookGroupDialog.OnGroup() {
override fun change() {
}
override fun addGroup(group: BookGroup) {
App.getHandler().postDelayed(
{ adapter.addItem(group) }, 300
)
}
})
}
}
}
}
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.recyclerView.adapter = adapter
val itemTouchCallback = ItemTouchCallback()
itemTouchCallback.setOnItemTouchListener(adapter)
itemTouchCallback.setLongPressDragEnable(true)
itemTouchHelper = ItemTouchHelper(itemTouchCallback)
itemTouchHelper.attachToRecyclerView(binding.recyclerView)
}
override fun initClick() {
super.initClick()
binding.rlBookGroup.setOnClickListener {
openGroup = !openGroup
binding.scBookGroup.isChecked = openGroup
SharedPreUtils.getInstance().putBoolean("openGroup", openGroup)
binding.recyclerView.visibility = if (openGroup) View.VISIBLE else View.GONE
setResult(RESULT_OK)
}
}
}

@ -263,6 +263,8 @@ public class MainActivity extends BaseActivity {
menu.setGroupVisible(R.id.bookcase_menu, true);
menu.findItem(R.id.action_finish).setVisible(false);
}
menu.findItem(R.id.action_change_group).setVisible(SharedPreUtils
.getInstance().getBoolean("openGroup"));
} else {
menu.setGroupVisible(R.id.bookcase_menu, false);
menu.findItem(R.id.action_finish).setVisible(false);
@ -307,7 +309,7 @@ public class MainActivity extends BaseActivity {
} else if (itemId == R.id.action_qr_scan) {
Intent intent = new Intent(this, QRCodeScanActivity.class);
startActivityForResult(intent, APPCONST.REQUEST_QR_SCAN);
} else if (itemId == R.id.action_refresh_find){
} else if (itemId == R.id.action_refresh_find) {
mFindFragment.refreshFind();
return true;
}
@ -388,6 +390,9 @@ public class MainActivity extends BaseActivity {
}
}
break;
case APPCONST.REQUEST_GROUP_MANAGER:
invalidateOptionsMenu();
break;
}
}
}

@ -0,0 +1,126 @@
package xyz.fycz.myreader.ui.adapter
import android.annotation.SuppressLint
import android.content.Context
import android.content.res.TypedArray
import android.os.AsyncTask
import android.util.TypedValue
import android.view.MotionEvent
import android.view.ViewGroup
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import org.jetbrains.anko.backgroundColor
import xyz.fycz.myreader.R
import xyz.fycz.myreader.application.App
import xyz.fycz.myreader.base.adapter2.ItemViewHolder
import xyz.fycz.myreader.base.adapter2.RecyclerAdapter
import xyz.fycz.myreader.databinding.ItemGroupBinding
import xyz.fycz.myreader.greendao.entity.BookGroup
import xyz.fycz.myreader.greendao.service.BookGroupService
import xyz.fycz.myreader.ui.adapter.helper.IItemTouchHelperViewHolder
import xyz.fycz.myreader.ui.adapter.helper.ItemTouchCallback
import xyz.fycz.myreader.ui.adapter.helper.OnStartDragListener
import xyz.fycz.myreader.ui.dialog.BookGroupDialog
import xyz.fycz.myreader.ui.dialog.DialogCreator
import xyz.fycz.myreader.util.ToastUtils
/**
* @author fengyue
* @date 2021/8/30 9:25
*/
class BookGroupAdapter(
context: Context,
private val onStartDragListener: OnStartDragListener,
private val groupDialog: BookGroupDialog,
) : RecyclerAdapter<BookGroup, ItemGroupBinding>(context),
ItemTouchCallback.OnItemTouchListener {
private var isMoved: Boolean = false
override fun getViewBinding(parent: ViewGroup): ItemGroupBinding {
return ItemGroupBinding.inflate(inflater, parent, false)
}
override fun convert(
holder: ItemViewHolder,
binding: ItemGroupBinding,
item: BookGroup,
payloads: MutableList<Any>
) {
binding.run {
tvGroupName.text = item.name
}
}
@SuppressLint("ClickableViewAccessibility")
override fun registerListener(holder: ItemViewHolder, binding: ItemGroupBinding) {
binding.run {
ivIcon.setOnClickListener {
val item = getItem(holder.layoutPosition)
DialogCreator.createCommonDialog(
context, "确定删除分组[" + item?.name + "]?",
"删除后,该书籍分组将永久不再显示,是否继续删除?", true,
"确定", "取消", { _, _ ->
BookGroupService.getInstance()
.deleteBookGroup(item)
removeItem(holder.layoutPosition)
groupDialog.initBookGroups(false)
ToastUtils.showSuccess("分组[" + item?.name + "]删除成功!")
}, null
)
}
ivMove.setOnTouchListener { _, motionEvent ->
if (motionEvent.action == MotionEvent.ACTION_DOWN) {
//通知ItemTouchHelper开始拖拽
onStartDragListener.onStartDrag(holder)
}
false
}
}
binding.root.setOnClickListener {
if (groupDialog.groupSize >= 50) {
ToastUtils.showWarring("分组数量不能超过50")
return@setOnClickListener
}
groupDialog.showAddOrRenameGroupDia(true, false,
holder.layoutPosition, object : BookGroupDialog.OnGroup() {
override fun change() {
App.getHandler().postDelayed(
{ notifyItemChanged(holder.layoutPosition) }, 300
)
}
})
}
}
override fun onMove(srcPosition: Int, targetPosition: Int): Boolean {
swapItem(srcPosition, targetPosition)
isMoved = true
return true
}
override fun onClearView(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder) {
if (isMoved) {
AsyncTask.execute {
for ((index, item) in getItems().withIndex()) {
item.num = index
}
BookGroupService.getInstance().updateGroups(getItems())
groupDialog.initBookGroups(false)
}
}
isMoved = false
}
/*override fun onItemSelected(viewHolder: RecyclerView.ViewHolder) {
viewHolder.itemView.backgroundColor = context.resources.getColor(R.color.colorBackground)
}
override fun onItemClear(viewHolder: RecyclerView.ViewHolder) {
val typedValue = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, typedValue, true)
val attribute = intArrayOf(android.R.attr.selectableItemBackground)
val typedArray = context.theme.obtainStyledAttributes(typedValue.resourceId, attribute)
viewHolder.itemView.background = typedArray.getDrawable(0)
}*/
}

@ -4,6 +4,7 @@ package xyz.fycz.myreader.ui.adapter;
import android.os.AsyncTask;
import androidx.fragment.app.FragmentActivity;
import androidx.recyclerview.widget.RecyclerView;
import java.util.Collections;
@ -26,36 +27,28 @@ public class BookSourceAdapter extends BaseSourceAdapter {
private OnStartDragListener onStartDragListener;
private boolean mEditState;
private final ItemTouchCallback.OnItemTouchListener itemTouchListener = new ItemTouchCallback.OnItemTouchListener() {
@Override
public void onSwiped(int adapterPosition) {
}
private boolean isMoved = true;
@Override
public boolean onMove(int srcPosition, int targetPosition) {
Collections.swap(mList, srcPosition, targetPosition);
notifyItemMoved(srcPosition, targetPosition);
/*notifyItemChanged(srcPosition);
notifyItemChanged(targetPosition);
AsyncTask.execute(() -> {
for (int i = 1; i <= mList.size(); i++) {
mList.get(i - 1).setOrderNum(i);
}
DbManager.getDaoSession().getBookSourceDao().insertOrReplaceInTx(mList);
});*/
swapItem(srcPosition, targetPosition);
isMoved = true;
return true;
}
@Override
public void onEnd() {
App.getHandler().postDelayed(() -> notifyDataSetChanged(), 500);
AsyncTask.execute(() -> {
for (int i = 1; i <= mList.size(); i++) {
mList.get(i - 1).setOrderNum(i);
}
DbManager.getDaoSession().getBookSourceDao().insertOrReplaceInTx(mList);
});
public void onClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (isMoved) {
App.getHandler().postDelayed(() -> notifyDataSetChanged(), 500);
AsyncTask.execute(() -> {
for (int i = 1; i <= mList.size(); i++) {
mList.get(i - 1).setOrderNum(i);
}
DbManager.getDaoSession().getBookSourceDao().insertOrReplaceInTx(mList);
});
}
isMoved = false;
}
};

@ -6,18 +6,19 @@ import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;
import android.view.View;
import android.widget.*;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.CheckBox;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SwitchCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.hjq.permissions.OnPermissionCallback;
import com.hjq.permissions.XXPermissions;
import com.kongzue.dialogx.dialogs.BottomDialog;
import com.kongzue.dialogx.dialogs.BottomMenu;
import com.kongzue.dialogx.interfaces.OnBindView;
import com.kongzue.dialogx.interfaces.OnDialogButtonClickListener;
import com.kongzue.dialogx.interfaces.OnMenuItemSelectListener;
import org.jetbrains.annotations.NotNull;
@ -28,17 +29,25 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import io.reactivex.Single;
import io.reactivex.SingleOnSubscribe;
import xyz.fycz.myreader.R;
import xyz.fycz.myreader.application.App;
import xyz.fycz.myreader.application.SysManager;
import xyz.fycz.myreader.base.BitIntentDataManager;
import xyz.fycz.myreader.base.observer.MySingleObserver;
import xyz.fycz.myreader.common.APPCONST;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.entity.rule.BookSource;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.model.sourceAnalyzer.BookSourceManager;
import xyz.fycz.myreader.ui.activity.BookDetailedActivity;
import xyz.fycz.myreader.ui.activity.BookInfoEditActivity;
@ -46,26 +55,20 @@ import xyz.fycz.myreader.ui.activity.SourceEditActivity;
import xyz.fycz.myreader.ui.adapter.helper.IItemTouchHelperViewHolder;
import xyz.fycz.myreader.ui.adapter.helper.ItemTouchCallback;
import xyz.fycz.myreader.ui.dialog.DialogCreator;
import xyz.fycz.myreader.ui.dialog.MyAlertDialog;
import xyz.fycz.myreader.ui.dialog.SourceExchangeDialog;
import xyz.fycz.myreader.ui.presenter.BookcasePresenter;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.help.StringHelper;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.util.utils.RxUtils;
import xyz.fycz.myreader.util.utils.ShareBookUtil;
import xyz.fycz.myreader.util.utils.StoragePermissionUtils;
import xyz.fycz.myreader.webapi.crawler.ReadCrawlerUtil;
import xyz.fycz.myreader.webapi.crawler.base.ReadCrawler;
import xyz.fycz.myreader.widget.BadgeView;
import xyz.fycz.myreader.widget.CoverImageView;
import xyz.fycz.myreader.widget.SwitchButton;
import xyz.fycz.myreader.widget.custom.DragAdapter;
import xyz.fycz.myreader.greendao.entity.Book;
import xyz.fycz.myreader.greendao.entity.Chapter;
import xyz.fycz.myreader.greendao.service.BookService;
import xyz.fycz.myreader.greendao.service.ChapterService;
import xyz.fycz.myreader.ui.presenter.BookcasePresenter;
import xyz.fycz.myreader.util.ToastUtils;
import xyz.fycz.myreader.util.utils.FileUtils;
import xyz.fycz.myreader.util.utils.NetworkUtils;
import xyz.fycz.myreader.widget.BadgeView;
/**
* @author fengyue
@ -179,9 +182,9 @@ public abstract class BookcaseAdapter extends RecyclerView.Adapter<BookcaseAdapt
mCheckMap.put(book.getId(), false);
}
mCheckedCount = 0;
} else {
} /*else {
onDataMove();
}
}*/
this.mEditState = mEditState;
notifyDataSetChanged();
}
@ -608,12 +611,12 @@ public abstract class BookcaseAdapter extends RecyclerView.Adapter<BookcaseAdapt
}
@Override
public void onItemSelected() {
public void onItemSelected(RecyclerView.ViewHolder viewHolder) {
itemView.setTranslationZ(10);
}
@Override
public void onItemClear() {
public void onItemClear(RecyclerView.ViewHolder viewHolder) {
itemView.setTranslationZ(0);
}
}

@ -2,6 +2,7 @@ package xyz.fycz.myreader.ui.adapter;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -9,6 +10,7 @@ import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.kongzue.dialogx.dialogs.BottomMenu;
@ -47,23 +49,22 @@ public class BookcaseDetailedAdapter extends BookcaseAdapter {
boolean editState, BookcasePresenter bookcasePresenter, boolean isGroup) {
super(context, textViewResourceId, objects, editState, bookcasePresenter, isGroup);
itemTouchCallbackListener = new ItemTouchCallback.OnItemTouchListener() {
@Override
public void onSwiped(int adapterPosition) {
}
private boolean isMoved = false;
@Override
public boolean onMove(int srcPosition, int targetPosition) {
Collections.swap(list, srcPosition, targetPosition);
notifyItemMoved(srcPosition, targetPosition);
/*notifyItemChanged(srcPosition);
notifyItemChanged(targetPosition);*/
isMoved = true;
return true;
}
@Override
public void onEnd() {
App.getHandler().postDelayed(() -> notifyDataSetChanged(), 500);
public void onClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (isMoved){
AsyncTask.execute(() -> onDataMove());
}
isMoved = false;
}
};

@ -2,11 +2,13 @@ package xyz.fycz.myreader.ui.adapter;
import android.content.Context;
import android.content.Intent;
import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.kongzue.dialogx.dialogs.BottomMenu;
@ -46,10 +48,7 @@ public class BookcaseDragAdapter extends BookcaseAdapter {
boolean editState, BookcasePresenter bookcasePresenter, boolean isGroup) {
super(context, textViewResourceId, objects, editState, bookcasePresenter, isGroup);
itemTouchCallbackListener = new ItemTouchCallback.OnItemTouchListener() {
@Override
public void onSwiped(int adapterPosition) {
}
private boolean isMoved = false;
@Override
public boolean onMove(int srcPosition, int targetPosition) {
@ -57,19 +56,16 @@ public class BookcaseDragAdapter extends BookcaseAdapter {
list.remove(srcPosition);
list.add(targetPosition, shelfBean);
notifyItemMoved(srcPosition, targetPosition);
/*int start = srcPosition;
int end = targetPosition;
if (start > end) {
start = targetPosition;
end = srcPosition;
}
notifyItemRangeChanged(start, end - start + 1);*/
isMoved = true;
return true;
}
@Override
public void onEnd() {
App.getHandler().postDelayed(() -> notifyDataSetChanged(), 500);
public void onClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (isMoved){
AsyncTask.execute(() -> onDataMove());
}
isMoved = false;
}
};

@ -1,5 +1,7 @@
package xyz.fycz.myreader.ui.adapter.helper;
import androidx.recyclerview.widget.RecyclerView;
/**
* @author fengyue
* @date 2021/6/3 17:47
@ -9,10 +11,10 @@ public interface IItemTouchHelperViewHolder {
/**
* item被选中在侧滑或拖拽过程中更新状态
*/
void onItemSelected();
void onItemSelected(RecyclerView.ViewHolder viewHolder);
/**
* item的拖拽或侧滑结束恢复默认的状态
*/
void onItemClear();
void onItemClear(RecyclerView.ViewHolder viewHolder);
}

@ -141,14 +141,14 @@ public class ItemTouchCallback extends ItemTouchHelper.Callback {
if (viewHolder instanceof IItemTouchHelperViewHolder) {
IItemTouchHelperViewHolder itemTouchHelperViewHolder =
(IItemTouchHelperViewHolder) viewHolder;
itemTouchHelperViewHolder.onItemSelected();
itemTouchHelperViewHolder.onItemSelected(viewHolder);
}
}
if (onItemTouchListener != null) {
/*if (onItemTouchListener != null) {
if (viewHolder == null) {
onItemTouchListener.onEnd();
}
}
}*/
super.onSelectedChanged(viewHolder, actionState);
final boolean swiping = actionState == ItemTouchHelper.ACTION_STATE_DRAG;
if (viewPager != null) {
@ -162,7 +162,10 @@ public class ItemTouchCallback extends ItemTouchHelper.Callback {
if (viewHolder instanceof IItemTouchHelperViewHolder) {
IItemTouchHelperViewHolder itemTouchHelperViewHolder =
(IItemTouchHelperViewHolder) viewHolder;
itemTouchHelperViewHolder.onItemClear();
itemTouchHelperViewHolder.onItemClear(viewHolder);
}
if (onItemTouchListener != null) {
onItemTouchListener.onClearView(recyclerView, viewHolder);
}
}
@ -177,7 +180,7 @@ public class ItemTouchCallback extends ItemTouchHelper.Callback {
*
* @param adapterPosition item的position
*/
void onSwiped(int adapterPosition);
default void onSwiped(int adapterPosition){}
/**
* 当两个Item位置互换的时候被回调
@ -191,6 +194,6 @@ public class ItemTouchCallback extends ItemTouchHelper.Callback {
/**
* 当滑动删除或拖拽结束时调用
*/
void onEnd();
void onClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder);
}
}

@ -202,12 +202,12 @@ public class BookSourceHolder extends ViewHolderImpl<BookSource> implements IIte
}
@Override
public void onItemSelected() {
public void onItemSelected(RecyclerView.ViewHolder viewHolder) {
getItemView().setTranslationZ(10);
}
@Override
public void onItemClear() {
public void onItemClear(RecyclerView.ViewHolder viewHolder) {
getItemView().setTranslationZ(0);
}
}

@ -79,12 +79,12 @@ public class BookStoreBookHolder extends ViewHolderImpl<Book> implements IItemTo
}
@Override
public void onItemSelected() {
public void onItemSelected(RecyclerView.ViewHolder viewHolder) {
getItemView().setTranslationZ(10);
}
@Override
public void onItemClear() {
public void onItemClear(RecyclerView.ViewHolder viewHolder) {
getItemView().setTranslationZ(0);
}
}

@ -3,6 +3,8 @@ package xyz.fycz.myreader.ui.adapter.holder;
import android.app.Activity;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
import androidx.recyclerview.widget.RecyclerView;
@ -105,6 +107,7 @@ public class FindBookHolder extends ViewHolderImpl<Book> {
}
});
}
setAnimation(holder.itemView, pos);
}
private void initOtherInfo(Book book, ReadCrawler rc) {
@ -149,4 +152,13 @@ public class FindBookHolder extends ViewHolderImpl<Book> {
if (StringHelper.isEmpty(bookBean.getNewestChapterTitle())) return true;
return StringHelper.isEmpty(bookBean.getImgUrl());
}
/**
* Here is the key method to apply the animation
*/
protected void setAnimation(View viewToAnimate, int position){
// If the bound view wasn't previously displayed on screen, it's animated
Animation animation =
AnimationUtils.loadAnimation(viewToAnimate.getContext(), R.anim.anim_recycle_item);
viewToAnimate.startAnimation(animation);
}
}

@ -35,7 +35,6 @@ public class BookGroupDialog {
private ArrayList<BookGroup> mBookGroups = new ArrayList<>();//书籍分组
private CharSequence[] mGroupNames;//书籍分组名称
private final BookGroupService mBookGroupService;
private Handler mHandler = new Handler();
private Context mContext;
public BookGroupDialog(Context context) {
@ -51,6 +50,10 @@ public class BookGroupDialog {
return mGroupNames;
}
public int getGroupSize() {
return mBookGroups.size();
}
//初始化书籍分组
public void initBookGroups(boolean isAdd) {
mBookGroups.clear();
@ -114,6 +117,10 @@ public class BookGroupDialog {
/**
* 添加/重命名分组对话框
* @param isRename
* @param isAddGroup 是否在将书籍添加分组对话框中调用
* @param groupNum
* @param onGroup
*/
public void showAddOrRenameGroupDia(boolean isRename, boolean isAddGroup, int groupNum, OnGroup onGroup) {
BookGroup bookGroup = !isRename ? new BookGroup() : mBookGroups.get(groupNum);
@ -141,8 +148,9 @@ public class BookGroupDialog {
ToastUtils.showSuccess("成功" +
(!isRename ? "添加分组[" : "成功将[" + oldName + "]重命名为[")
+ bookGroup.getName() + "]");
initBookGroups(false);
if (isAddGroup) {
if (onGroup != null) onGroup.addGroup();
if (onGroup != null) onGroup.addGroup(bookGroup);
}
});
}
@ -192,7 +200,7 @@ public class BookGroupDialog {
public abstract static class OnGroup {
public abstract void change();
public void addGroup() {
public void addGroup(BookGroup group) {
}
}

@ -243,7 +243,7 @@ public class BookcasePresenter implements BasePresenter {
}
@Override
public void addGroup() {
public void addGroup(BookGroup group) {
mBookcaseFragment.getmBtnAddGroup().performClick();
}
});
@ -368,7 +368,7 @@ public class BookcasePresenter implements BasePresenter {
book.setNoReadNum(Math.max(noReadNum, 0));
book.setNewestChapterTitle(chapters.get(chapters.size() - 1).getTitle());
mChapterService.updateAllOldChapterData(mChapters, chapters, book.getId());
if (book.getHisttoryChapterNum() + 1 > chapters.size()){
if (book.getHisttoryChapterNum() + 1 > chapters.size()) {
book.setHisttoryChapterNum(chapters.size() - 1);
}
mBookService.updateEntity(book);
@ -499,7 +499,11 @@ public class BookcasePresenter implements BasePresenter {
init();
return true;
} else if (itemId == R.id.action_group_man) {
showGroupManDia();
//showGroupManDia();
mMainActivity.startActivityForResult(
new Intent(mMainActivity, GroupManagerActivity.class),
APPCONST.REQUEST_GROUP_MANAGER
);
return true;
} else if (itemId == R.id.action_addLocalBook) {
addLocalBook();
@ -586,7 +590,6 @@ public class BookcasePresenter implements BasePresenter {
mBookcaseFragment.getRlBookEdit().startAnimation(mMainActivity.getmBottomInAnim());
setBtnClickable(false);
changeCheckedAllStatus();
mBookcaseAdapter.notifyDataSetChanged();
} else {
ToastUtils.showWarring("当前无任何书籍,无法编辑书架!");
}
@ -598,7 +601,6 @@ public class BookcasePresenter implements BasePresenter {
mBookcaseFragment.getRlBookEdit().setVisibility(View.GONE);
mMainActivity.initMenuAnim();
mBookcaseFragment.getRlBookEdit().startAnimation(mMainActivity.getmBottomOutAnim());
mBookcaseAdapter.notifyDataSetChanged();
}
}
@ -667,7 +669,7 @@ public class BookcasePresenter implements BasePresenter {
}
@Override
public void addGroup() {
public void addGroup(BookGroup group) {
mBookcaseFragment.getmBtnAddGroup().performClick();
}
});
@ -681,7 +683,7 @@ public class BookcasePresenter implements BasePresenter {
}
@Override
public void addGroup() {
public void addGroup(BookGroup group) {
mBookcaseFragment.getmBtnAddGroup().performClick();
}
});
@ -720,7 +722,7 @@ public class BookcasePresenter implements BasePresenter {
}
@Override
public void addGroup() {
public void addGroup(BookGroup group) {
BookcasePresenter.this.addGroup(book);
}
});

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:interpolator="@android:anim/decelerate_interpolator"
>
<translate
android:fromYDelta="200%"
android:toYDelta="0%"
android:duration="750"
/>
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"
android:duration="750"/>
<!-- <scale-->
<!-- android:pivotX="50%"-->
<!-- android:pivotY="50%"-->
<!-- android:fromXScale="0.5"-->
<!-- android:fromYScale="0.5"-->
<!-- android:toXScale="1"-->
<!-- android:toYScale="1"-->
<!-- android:duration="750"-->
<!-- />-->
</set>

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M767.98,815.98c-12.31,0 -24.56,-4.69 -33.94,-14.06l-512,-512c-18.75,-18.75 -18.75,-49.12 0,-67.88s49.13,-18.75 67.88,0l512,512c18.75,18.75 18.75,49.12 0,67.88 -9.38,9.38 -21.63,14.06 -33.94,14.06z"
android:fillColor="#ffffff"/>
<path
android:pathData="M255.98,815.98c-12.31,0 -24.56,-4.69 -33.94,-14.06 -18.75,-18.75 -18.75,-49.12 0,-67.88l512,-512c18.75,-18.75 49.12,-18.75 67.88,0s18.75,49.12 0,67.88l-512,512c-9.38,9.38 -21.63,14.06 -33.94,14.06z"
android:fillColor="#ffffff"/>
</vector>

@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="1024"
android:viewportHeight="1024">
<path
android:pathData="M512,912.03c-26.5,0 -48,-21.5 -48,-48v-704c0,-26.5 21.5,-48 48,-48s48,21.5 48,48v704c0,26.5 -21.5,48 -48,48z"
android:fillColor="#ffffff"/>
<path
android:pathData="M864,560.03H160c-26.5,0 -48,-21.5 -48,-48s21.5,-48 48,-48h704c26.5,0 48,21.5 48,48s-21.5,48 -48,48z"
android:fillColor="#ffffff"/>
</vector>

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar" />
<RelativeLayout
android:id="@+id/rl_book_group"
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/selector_common_bg"
android:gravity="center"
android:paddingLeft="20dp"
android:paddingRight="20dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:background="@drawable/selector_common_bg"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/book_group"
android:textColor="@color/textSecondary"
android:textSize="@dimen/text_normal_size" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:text="@string/book_group_tip"
android:textColor="@color/textAssist" />
</LinearLayout>
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/sc_book_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:clickable="false"
android:longClickable="false" />
</RelativeLayout>
<View
android:layout_width="match_parent"
android:layout_height="15dp" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:background="@color/colorForeground"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>

@ -31,7 +31,7 @@
android:longClickable="false" />
</RelativeLayout>
<LinearLayout
<View
android:layout_height="15dp"
android:layout_width="match_parent" />

@ -0,0 +1,42 @@
<?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="match_parent"
android:layout_height="50dp"
android:background="?android:attr/selectableItemBackground"
android:gravity="center_vertical"
android:paddingHorizontal="10dp"
android:paddingVertical="5dp">
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_icon"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:paddingHorizontal="5dp"
app:srcCompat="@drawable/ic_cross"
app:tint="@color/md_red_600" />
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/tv_group_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:layout_toStartOf="@id/iv_move"
android:layout_toEndOf="@+id/iv_icon"
android:paddingHorizontal="10dp"
android:text="@string/app_name"
android:textColor="@color/textPrimary"
android:textSize="@dimen/text_normal_size" />
<androidx.appcompat.widget.AppCompatImageView
android:id="@+id/iv_move"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:layout_centerVertical="true"
android:padding="8dp"
app:srcCompat="@drawable/ic_line_spacing3"
app:tint="@color/textAssist" />
</RelativeLayout>

@ -507,6 +507,9 @@
<string name="backup_path">备份路径</string>
<string name="cathe_path">缓存路径</string>
<string name="sort_type">排序方式</string>
<string name="manage_book_group">管理书籍分组</string>
<string name="book_group">书籍分组</string>
<string name="book_group_tip">在书架内显示书籍分组</string>
<string-array name="reset_screen_time">

Loading…
Cancel
Save