From 3ddcaaff76a310e67877dd23dfc65bd925792f20 Mon Sep 17 00:00:00 2001 From: fengyuecanzhu <1021300691@qq.com> Date: Mon, 30 Aug 2021 16:33:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=88=86=E7=BB=84=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E7=95=8C=E9=9D=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .idea/assetWizardSettings.xml | 4 +- .idea/misc.xml | 7 + app/src/main/AndroidManifest.xml | 1 + .../fycz/myreader/application/SysManager.java | 4 + .../base/adapter/BaseListAdapter.java | 86 +++++++----- .../myreader/base/adapter/ViewHolderImpl.java | 7 +- .../xyz/fycz/myreader/common/APPCONST.java | 3 +- .../greendao/service/BookGroupService.java | 9 +- .../ui/activity/GroupManagerActivity.kt | 111 +++++++++++++++ .../myreader/ui/activity/MainActivity.java | 7 +- .../myreader/ui/adapter/BookGroupAdapter.kt | 126 ++++++++++++++++++ .../ui/adapter/BookSourceAdapter.java | 37 +++-- .../myreader/ui/adapter/BookcaseAdapter.java | 47 ++++--- .../ui/adapter/BookcaseDetailedAdapter.java | 17 +-- .../ui/adapter/BookcaseDragAdapter.java | 22 ++- .../helper/IItemTouchHelperViewHolder.java | 6 +- .../ui/adapter/helper/ItemTouchCallback.java | 15 ++- .../ui/adapter/holder/BookSourceHolder.java | 4 +- .../adapter/holder/BookStoreBookHolder.java | 4 +- .../ui/adapter/holder/FindBookHolder.java | 12 ++ .../myreader/ui/dialog/BookGroupDialog.java | 14 +- .../ui/presenter/BookcasePresenter.java | 18 +-- app/src/main/res/anim/anim_recycle_item.xml | 31 +++++ app/src/main/res/drawable/ic_cross.xml | 12 ++ app/src/main/res/drawable/ic_plus.xml | 12 ++ .../res/layout/activity_group_manager.xml | 60 +++++++++ .../res/layout/fragment_private_bookcase.xml | 2 +- app/src/main/res/layout/item_group.xml | 42 ++++++ app/src/main/res/values/strings.xml | 3 + 29 files changed, 592 insertions(+), 131 deletions(-) create mode 100644 app/src/main/java/xyz/fycz/myreader/ui/activity/GroupManagerActivity.kt create mode 100644 app/src/main/java/xyz/fycz/myreader/ui/adapter/BookGroupAdapter.kt create mode 100644 app/src/main/res/anim/anim_recycle_item.xml create mode 100644 app/src/main/res/drawable/ic_cross.xml create mode 100644 app/src/main/res/drawable/ic_plus.xml create mode 100644 app/src/main/res/layout/activity_group_manager.xml create mode 100644 app/src/main/res/layout/item_group.xml diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml index 89ab429..60a072d 100644 --- a/.idea/assetWizardSettings.xml +++ b/.idea/assetWizardSettings.xml @@ -14,8 +14,8 @@ diff --git a/.idea/misc.xml b/.idea/misc.xml index a087172..6e2cee0 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -6,9 +6,16 @@ + + + + + + + diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 4a886b7..39773f2 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -119,6 +119,7 @@ + diff --git a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java index cc84b37..9d6c75b 100644 --- a/app/src/main/java/xyz/fycz/myreader/application/SysManager.java +++ b/app/src/main/java/xyz/fycz/myreader/application/SysManager.java @@ -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); diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java b/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java index 670164b..d550a1d 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/base/adapter/BaseListAdapter.java @@ -49,23 +49,23 @@ public abstract class BaseListAdapter extends RecyclerView.Adapter{ - 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 extends RecyclerView.Adapter extends RecyclerView.Adapter values){ - mList.addAll(values); - - Handler handler = new Handler(); - handler.post(new Runnable() { - @Override - public void run() { + public synchronized void addItems(List 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 value){ - mList.removeAll(value); - notifyDataSetChanged(); + public synchronized void removeItems(List 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 getItems(){ + public List getItems() { return Collections.unmodifiableList(mList); } - public int getItemSize(){ + public int getItemSize() { return mList.size(); } - public void refreshItems(List list){ + public synchronized void refreshItems(List 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); } } diff --git a/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java b/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java index 3c3499e..5136fe0 100644 --- a/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java +++ b/app/src/main/java/xyz/fycz/myreader/base/adapter/ViewHolderImpl.java @@ -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 implements IViewHolder { /****************************************************/ protected abstract int getItemLayoutId(); - @Override public View createItemView(ViewGroup parent) { view = LayoutInflater.from(parent.getContext()) diff --git a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java index 6401ab7..2388d68 100644 --- a/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java +++ b/app/src/main/java/xyz/fycz/myreader/common/APPCONST.java @@ -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; diff --git a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java index c90bb68..86a791f 100644 --- a/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java +++ b/app/src/main/java/xyz/fycz/myreader/greendao/service/BookGroupService.java @@ -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 groups) { + BookGroupDao bookDao = DbManager.getInstance().getSession().getBookGroupDao(); + bookDao.insertOrReplaceInTx(groups); + } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/GroupManagerActivity.kt b/app/src/main/java/xyz/fycz/myreader/ui/activity/GroupManagerActivity.kt new file mode 100644 index 0000000..e8d1862 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/GroupManagerActivity.kt @@ -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) + } + } + +} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java b/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java index 3c1643d..42d67a1 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/activity/MainActivity.java @@ -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; } } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookGroupAdapter.kt b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookGroupAdapter.kt new file mode 100644 index 0000000..51cfa36 --- /dev/null +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookGroupAdapter.kt @@ -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(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 + ) { + 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) + }*/ +} \ No newline at end of file diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookSourceAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookSourceAdapter.java index ab7aa16..9dcc011 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookSourceAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookSourceAdapter.java @@ -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; } }; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java index 159bba6..c93f528 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseAdapter.java @@ -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 notifyDataSetChanged(), 500); + public void onClearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { + if (isMoved){ + AsyncTask.execute(() -> onDataMove()); + } + isMoved = false; } }; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java index a64b290..42a8ddd 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/BookcaseDragAdapter.java @@ -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; } }; diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/IItemTouchHelperViewHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/IItemTouchHelperViewHolder.java index 78cdd0c..cd7d3ad 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/IItemTouchHelperViewHolder.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/IItemTouchHelperViewHolder.java @@ -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); } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/ItemTouchCallback.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/ItemTouchCallback.java index 7c0eaa5..d0905e6 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/ItemTouchCallback.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/helper/ItemTouchCallback.java @@ -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); } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookSourceHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookSourceHolder.java index f2657b2..c142be4 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookSourceHolder.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookSourceHolder.java @@ -202,12 +202,12 @@ public class BookSourceHolder extends ViewHolderImpl 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); } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java index 26322f6..3d88962 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/BookStoreBookHolder.java @@ -79,12 +79,12 @@ public class BookStoreBookHolder extends ViewHolderImpl 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); } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java index 62dfb5d..7861583 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/adapter/holder/FindBookHolder.java @@ -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 { } }); } + setAnimation(holder.itemView, pos); } private void initOtherInfo(Book book, ReadCrawler rc) { @@ -149,4 +152,13 @@ public class FindBookHolder extends ViewHolderImpl { 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); + } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java b/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java index 73afbef..c266def 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/dialog/BookGroupDialog.java @@ -35,7 +35,6 @@ public class BookGroupDialog { private ArrayList 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) { } } diff --git a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java index 6e57b1e..27270db 100644 --- a/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java +++ b/app/src/main/java/xyz/fycz/myreader/ui/presenter/BookcasePresenter.java @@ -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); } }); diff --git a/app/src/main/res/anim/anim_recycle_item.xml b/app/src/main/res/anim/anim_recycle_item.xml new file mode 100644 index 0000000..0e12bc4 --- /dev/null +++ b/app/src/main/res/anim/anim_recycle_item.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_cross.xml b/app/src/main/res/drawable/ic_cross.xml new file mode 100644 index 0000000..3fa4ed5 --- /dev/null +++ b/app/src/main/res/drawable/ic_cross.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_plus.xml b/app/src/main/res/drawable/ic_plus.xml new file mode 100644 index 0000000..75fa8d4 --- /dev/null +++ b/app/src/main/res/drawable/ic_plus.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/activity_group_manager.xml b/app/src/main/res/layout/activity_group_manager.xml new file mode 100644 index 0000000..d8928a0 --- /dev/null +++ b/app/src/main/res/layout/activity_group_manager.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_private_bookcase.xml b/app/src/main/res/layout/fragment_private_bookcase.xml index 530d196..6583fce 100644 --- a/app/src/main/res/layout/fragment_private_bookcase.xml +++ b/app/src/main/res/layout/fragment_private_bookcase.xml @@ -31,7 +31,7 @@ android:longClickable="false" /> - diff --git a/app/src/main/res/layout/item_group.xml b/app/src/main/res/layout/item_group.xml new file mode 100644 index 0000000..3a958f9 --- /dev/null +++ b/app/src/main/res/layout/item_group.xml @@ -0,0 +1,42 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 819c7d2..3c8dedd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -507,6 +507,9 @@ 备份路径 缓存路径 排序方式 + 管理书籍分组 + 书籍分组 + 在书架内显示书籍分组