diff --git a/.idea/misc.xml b/.idea/misc.xml index 6d5dd44..89482aa 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -10,7 +10,7 @@ - + diff --git a/app/src/main/java/com/novel/read/activity/NovelSearchActivity.kt b/app/src/main/java/com/novel/read/activity/NovelSearchActivity.kt index 0cf6c85..2f0002d 100644 --- a/app/src/main/java/com/novel/read/activity/NovelSearchActivity.kt +++ b/app/src/main/java/com/novel/read/activity/NovelSearchActivity.kt @@ -1,5 +1,6 @@ package com.novel.read.activity +import android.content.DialogInterface import android.text.Editable import android.text.TextUtils import android.text.TextWatcher @@ -169,16 +170,16 @@ class NovelSearchActivity : NovelBaseActivity() { saveKey() } head_history.setOnClickListener { view -> - DialogUtils.getInstance() - .showAlertDialog( - this@NovelSearchActivity, - getString(R.string.clear_search) - ) { dialogInterface, i -> + + DialogUtils.getInstance().showAlertDialog( + this, + getString(R.string.clear_search), + dialogListener = DialogInterface.OnClickListener { dialog, which -> LitePal.deleteAll(SearchListTable::class.java) mHisList.clear() mHisList.addAll(LitePal.order("saveTime desc").limit(5).find(SearchListTable::class.java)) mHisAdapter!!.notifyDataSetChanged() - } + }) } tv_cancel.setOnClickListener { diff --git a/app/src/main/java/com/novel/read/utlis/Charset.java b/app/src/main/java/com/novel/read/utlis/Charset.java index 186758d..3632774 100644 --- a/app/src/main/java/com/novel/read/utlis/Charset.java +++ b/app/src/main/java/com/novel/read/utlis/Charset.java @@ -12,7 +12,7 @@ public enum Charset { private String mName; public static final byte BLANK = 0x0a; - private Charset(String name) { + Charset(String name) { mName = name; } diff --git a/app/src/main/java/com/novel/read/utlis/CleanCacheUtils.java b/app/src/main/java/com/novel/read/utlis/CleanCacheUtils.java deleted file mode 100644 index db06995..0000000 --- a/app/src/main/java/com/novel/read/utlis/CleanCacheUtils.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.novel.read.utlis; - -import android.content.Context; -import android.os.Environment; - -import com.novel.read.model.db.BookChapterBean; -import com.novel.read.model.db.CollBookBean; -import com.novel.read.model.db.SearchListTable; - -import org.litepal.LitePal; - -import java.io.File; -import java.math.BigDecimal; - -/** - * @author: LiJun 390057892@qq.com - * @date: 2018/4/11 16:00 - */ - -public class CleanCacheUtils { - - private static CleanCacheUtils manager; - - public static CleanCacheUtils getInstance() { - return manager == null ? (manager = new CleanCacheUtils()) : manager; - } - - /** - * @param context - * @return - * @throws Exception - * 获取当前缓存 - */ - public String getTotalCacheSize(Context context) throws Exception { - long cacheSize = getFolderSize(context.getCacheDir()); - if (Environment.getExternalStorageState().equals( - Environment.MEDIA_MOUNTED)) { - cacheSize += getFolderSize(context.getExternalCacheDir()); - } - return getFormatSize(cacheSize); - } - - /** - * @param context - * 删除缓存 - */ - public static void clearAllCache(Context context) { - deleteDir(context.getCacheDir()); - if (Environment.getExternalStorageState().equals( - Environment.MEDIA_MOUNTED)) { - deleteDir(context.getExternalCacheDir()); - } - } - - private static boolean deleteDir(File dir) { - if (dir != null && dir.isDirectory()) { - String[] children = dir.list(); - int size = 0; - if (children != null) { - size = children.length; - for (int i = 0; i < size; i++) { - boolean success = deleteDir(new File(dir, children[i])); - if (!success) { - return false; - } - } - } - - } - if (dir == null) { - return true; - } else { - - return dir.delete(); - } - } - - // 获取文件 - // Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ - // 目录,一般放一些长时间保存的数据 - // Context.getExternalCacheDir() --> - // SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据 - public static long getFolderSize(File file) throws Exception { - long size = 0; - try { - File[] fileList = file.listFiles(); - int size2 = 0; - if (fileList != null) { - size2 = fileList.length; - for (int i = 0; i < size2; i++) { - // 如果下面还有文件 - if (fileList[i].isDirectory()) { - size = size + getFolderSize(fileList[i]); - } else { - size = size + fileList[i].length(); - } - } - } - - } catch (Exception e) { - e.printStackTrace(); - } - return size; - } - - /** - * 格式化单位 - * 计算缓存的大小 - * @param size - * @return - */ - public static String getFormatSize(double size) { - double kiloByte = size / 1024; - if (kiloByte < 1) { - // return size + "Byte"; - return "0K"; - } - - double megaByte = kiloByte / 1024; - if (megaByte < 1) { - BigDecimal result1 = new BigDecimal(Double.toString(kiloByte)); - return result1.setScale(2, BigDecimal.ROUND_HALF_UP) - .toPlainString() + "KB"; - } - - double gigaByte = megaByte / 1024; - if (gigaByte < 1) { - BigDecimal result2 = new BigDecimal(Double.toString(megaByte)); - return result2.setScale(2, BigDecimal.ROUND_HALF_UP) - .toPlainString() + "MB"; - } - - double teraBytes = gigaByte / 1024; - if (teraBytes < 1) { - BigDecimal result3 = new BigDecimal(Double.toString(gigaByte)); - return result3.setScale(2, BigDecimal.ROUND_HALF_UP) - .toPlainString() + "GB"; - } - BigDecimal result4 = new BigDecimal(teraBytes); - return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() - + "TB"; - } - - - /** - * 清除缓存 - * - * @param clearReadPos 是否删除阅读记录 - */ - public synchronized void clearCache(boolean clearReadPos, boolean clearCollect,Context context) { - try { - clearAllCache(context); - // 删除搜索记录(SharePreference) - if (clearReadPos) { - LitePal.deleteAll(SearchListTable.class); - } - // 清空书架 - if (clearCollect) { - LitePal.deleteAll(CollBookBean.class); - LitePal.deleteAll(BookChapterBean.class); - } - } catch (Exception e) { - } - } - -} diff --git a/app/src/main/java/com/novel/read/utlis/CleanCacheUtils.kt b/app/src/main/java/com/novel/read/utlis/CleanCacheUtils.kt new file mode 100644 index 0000000..0e15a1b --- /dev/null +++ b/app/src/main/java/com/novel/read/utlis/CleanCacheUtils.kt @@ -0,0 +1,170 @@ +package com.novel.read.utlis + +import android.content.Context +import android.os.Environment + +import com.novel.read.model.db.BookChapterBean +import com.novel.read.model.db.CollBookBean +import com.novel.read.model.db.SearchListTable + +import org.litepal.LitePal + +import java.io.File +import java.math.BigDecimal + +/** + * @author: LiJun 390057892@qq.com + * @date: 2018/4/11 16:00 + */ + +class CleanCacheUtils { + + /** + * @param context + * @return + * @throws Exception + * 获取当前缓存 + */ + @Throws(Exception::class) + fun getTotalCacheSize(context: Context): String { + var cacheSize = getFolderSize(context.cacheDir) + if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { + cacheSize += getFolderSize(context.externalCacheDir) + } + return getFormatSize(cacheSize.toDouble()) + } + + + /** + * 清除缓存 + * + * @param clearReadPos 是否删除阅读记录 + */ + @Synchronized + fun clearCache(clearReadPos: Boolean, clearCollect: Boolean, context: Context) { + try { + clearAllCache(context) + // 删除搜索记录(SharePreference) + if (clearReadPos) { + LitePal.deleteAll(SearchListTable::class.java) + } + // 清空书架 + if (clearCollect) { + LitePal.deleteAll(CollBookBean::class.java) + LitePal.deleteAll(BookChapterBean::class.java) + } + } catch (e: Exception) { + } + + } + + companion object { + + private var instance: CleanCacheUtils? = null + + @Synchronized + fun getInstance(): CleanCacheUtils { + if (instance == null) { + instance = CleanCacheUtils() + } + return instance as CleanCacheUtils + } + + /** + * @param context + * 删除缓存 + */ + fun clearAllCache(context: Context) { + deleteDir(context.cacheDir) + if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) { + deleteDir(context.externalCacheDir) + } + } + + private fun deleteDir(dir: File?): Boolean { + if (dir != null && dir.isDirectory) { + val children = dir.list() + var size = 0 + if (children != null) { + size = children.size + for (i in 0 until size) { + val success = deleteDir(File(dir, children[i])) + if (!success) { + return false + } + } + } + + } + return dir?.delete() ?: true + } + + // 获取文件 + // Context.getExternalFilesDir() --> SDCard/Android/data/你的应用的包名/files/ + // 目录,一般放一些长时间保存的数据 + // Context.getExternalCacheDir() --> + // SDCard/Android/data/你的应用包名/cache/目录,一般存放临时缓存数据 + @Throws(Exception::class) + fun getFolderSize(file: File?): Long { + var size: Long = 0 + try { + val fileList = file!!.listFiles() + var size2 = 0 + if (fileList != null) { + size2 = fileList.size + for (i in 0 until size2) { + // 如果下面还有文件 + if (fileList[i].isDirectory) { + size = size + getFolderSize(fileList[i]) + } else { + size = size + fileList[i].length() + } + } + } + + } catch (e: Exception) { + e.printStackTrace() + } + + return size + } + + /** + * 格式化单位 + * 计算缓存的大小 + * @param size + * @return + */ + fun getFormatSize(size: Double): String { + val kiloByte = size / 1024 + if (kiloByte < 1) { + // return size + "Byte"; + return "0K" + } + + val megaByte = kiloByte / 1024 + if (megaByte < 1) { + val result1 = BigDecimal(java.lang.Double.toString(kiloByte)) + return result1.setScale(2, BigDecimal.ROUND_HALF_UP) + .toPlainString() + "KB" + } + + val gigaByte = megaByte / 1024 + if (gigaByte < 1) { + val result2 = BigDecimal(java.lang.Double.toString(megaByte)) + return result2.setScale(2, BigDecimal.ROUND_HALF_UP) + .toPlainString() + "MB" + } + + val teraBytes = gigaByte / 1024 + if (teraBytes < 1) { + val result3 = BigDecimal(java.lang.Double.toString(gigaByte)) + return result3.setScale(2, BigDecimal.ROUND_HALF_UP) + .toPlainString() + "GB" + } + val result4 = BigDecimal(teraBytes) + return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString() + "TB" + } + } + +} diff --git a/app/src/main/java/com/novel/read/utlis/DialogUtils.java b/app/src/main/java/com/novel/read/utlis/DialogUtils.java deleted file mode 100644 index f56ef7b..0000000 --- a/app/src/main/java/com/novel/read/utlis/DialogUtils.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.novel.read.utlis; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; - -/** - * create by zlj on 2019/6/19 - * describe: - */ -public class DialogUtils { - - private static DialogUtils dialogUtils; - - public static DialogUtils getInstance() { - if (dialogUtils == null) { - dialogUtils = new DialogUtils(); - } - return dialogUtils; - } - - private DialogUtils() { } - - public void showAlertDialog(Context context, String msg, DialogInterface.OnClickListener dialogListener) { - // context = context.getApplicationContext(); - AlertDialog.Builder builder = new AlertDialog.Builder(context); - builder.setTitle("操作提示").setMessage(msg).setCancelable(false).setPositiveButton("确定", dialogListener).setNegativeButton("取消", new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, int id) { - dialog.cancel(); - } - }); - AlertDialog alert = builder.create(); - alert.show(); - } -} diff --git a/app/src/main/java/com/novel/read/utlis/DialogUtils.kt b/app/src/main/java/com/novel/read/utlis/DialogUtils.kt new file mode 100644 index 0000000..09e3b1a --- /dev/null +++ b/app/src/main/java/com/novel/read/utlis/DialogUtils.kt @@ -0,0 +1,39 @@ +package com.novel.read.utlis + +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface + +/** + * create by zlj on 2019/6/19 + * describe: + */ +class DialogUtils private constructor() { + + fun showAlertDialog( + context: Context, + msg: String, + dialogListener: DialogInterface.OnClickListener + ) { + // context = context.getApplicationContext(); + val builder = AlertDialog.Builder(context) + builder.setTitle("操作提示").setMessage(msg).setCancelable(false) + .setPositiveButton("确定", dialogListener) + .setNegativeButton("取消") { dialog, id -> dialog.cancel() } + val alert = builder.create() + alert.show() + } + + companion object { + + private var instance: DialogUtils? = null + + @Synchronized + fun getInstance(): DialogUtils { + if (instance == null) { + instance = DialogUtils() + } + return instance as DialogUtils + } + } +} diff --git a/app/src/main/java/com/novel/read/widget/page/PageMode.java b/app/src/main/java/com/novel/read/widget/page/PageMode.kt similarity index 64% rename from app/src/main/java/com/novel/read/widget/page/PageMode.java rename to app/src/main/java/com/novel/read/widget/page/PageMode.kt index 58dac4b..92d9ac7 100644 --- a/app/src/main/java/com/novel/read/widget/page/PageMode.java +++ b/app/src/main/java/com/novel/read/widget/page/PageMode.kt @@ -1,9 +1,9 @@ -package com.novel.read.widget.page; +package com.novel.read.widget.page /** * Created by zlj * 作用:翻页动画的模式 */ -public enum PageMode { +enum class PageMode { SIMULATION, COVER, SLIDE, NONE, SCROLL } diff --git a/app/src/main/java/com/novel/read/widget/page/PageStyle.java b/app/src/main/java/com/novel/read/widget/page/PageStyle.java deleted file mode 100644 index 86f5a3e..0000000 --- a/app/src/main/java/com/novel/read/widget/page/PageStyle.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.novel.read.widget.page; - - -import androidx.annotation.ColorRes; - -import com.novel.read.R; - -/** - * Created by zlj - * 页面的展示风格。 - */ -public enum PageStyle { - BG_0(R.color.read_font_one, R.color.read_bg_one), - BG_1(R.color.read_font_two, R.color.read_bg_two), -// BG_2(R.color.nb_read_font_3, R.color.nb_read_bg_3), - BG_3(R.color.read_font_four, R.color.read_bg_four), - BG_4(R.color.read_font_five, R.color.read_bg_five), - NIGHT(R.color.read_font_night, R.color.read_bg_night),; - - private int fontColor; - private int bgColor; - - PageStyle(@ColorRes int fontColor, @ColorRes int bgColor) { - this.fontColor = fontColor; - this.bgColor = bgColor; - } - - public int getFontColor() { - return fontColor; - } - - public int getBgColor() { - return bgColor; - } -} diff --git a/app/src/main/java/com/novel/read/widget/page/PageStyle.kt b/app/src/main/java/com/novel/read/widget/page/PageStyle.kt new file mode 100644 index 0000000..6082c79 --- /dev/null +++ b/app/src/main/java/com/novel/read/widget/page/PageStyle.kt @@ -0,0 +1,19 @@ +package com.novel.read.widget.page + + +import androidx.annotation.ColorRes + +import com.novel.read.R + +/** + * Created by zlj + * 页面的展示风格。 + */ +enum class PageStyle private constructor(@param:ColorRes val fontColor: Int, @param:ColorRes val bgColor: Int) { + BG_0(R.color.read_font_one, R.color.read_bg_one), + BG_1(R.color.read_font_two, R.color.read_bg_two), + // BG_2(R.color.nb_read_font_3, R.color.nb_read_bg_3), + BG_3(R.color.read_font_four, R.color.read_bg_four), + BG_4(R.color.read_font_five, R.color.read_bg_five), + NIGHT(R.color.read_font_night, R.color.read_bg_night) +} diff --git a/app/src/main/java/com/novel/read/widget/page/PageView.java b/app/src/main/java/com/novel/read/widget/page/PageView.java index 8f72791..6b459a2 100644 --- a/app/src/main/java/com/novel/read/widget/page/PageView.java +++ b/app/src/main/java/com/novel/read/widget/page/PageView.java @@ -310,7 +310,7 @@ public class PageView extends View { public void drawCurPage(boolean isUpdate) { if (!isPrepare) return; - if (!isUpdate){ + if (!isUpdate) { if (mPageAnim instanceof ScrollPageAnim) { ((ScrollPageAnim) mPageAnim).resetBitmap(); } diff --git a/app/src/main/java/com/novel/read/widget/page/Void.java b/app/src/main/java/com/novel/read/widget/page/Void.java deleted file mode 100644 index 73c6948..0000000 --- a/app/src/main/java/com/novel/read/widget/page/Void.java +++ /dev/null @@ -1,4 +0,0 @@ -package com.novel.read.widget.page; - -public final class Void { -} diff --git a/app/src/main/java/com/novel/read/widget/page/Void.kt b/app/src/main/java/com/novel/read/widget/page/Void.kt new file mode 100644 index 0000000..9f07962 --- /dev/null +++ b/app/src/main/java/com/novel/read/widget/page/Void.kt @@ -0,0 +1,3 @@ +package com.novel.read.widget.page + +class Void diff --git a/app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.java b/app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.java deleted file mode 100644 index 2f69300..0000000 --- a/app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.novel.read.widget.page.anim; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.graphics.drawable.GradientDrawable; -import android.view.View; - -/** - * Created by zlj - * 覆盖动画 - */ - -public class CoverPageAnim extends HorizonPageAnim { - - private Rect mSrcRect, mDestRect; - private GradientDrawable mBackShadowDrawableLR; - - public CoverPageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - mSrcRect = new Rect(0, 0, mViewWidth, mViewHeight); - mDestRect = new Rect(0, 0, mViewWidth, mViewHeight); - int[] mBackShadowColors = new int[] { 0x66000000,0x00000000}; - mBackShadowDrawableLR = new GradientDrawable( - GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors); - mBackShadowDrawableLR.setGradientType(GradientDrawable.LINEAR_GRADIENT); - } - - @Override - public void drawStatic(Canvas canvas) { - if (isCancel){ - mNextBitmap = mCurBitmap.copy(Bitmap.Config.RGB_565, true); - canvas.drawBitmap(mCurBitmap, 0, 0, null); - }else { - canvas.drawBitmap(mNextBitmap, 0, 0, null); - } - } - - @Override - public void drawMove(Canvas canvas) { - - switch (mDirection){ - case NEXT: - int dis = (int) (mViewWidth - mStartX + mTouchX); - if (dis > mViewWidth){ - dis = mViewWidth; - } - //计算bitmap截取的区域 - mSrcRect.left = mViewWidth - dis; - //计算bitmap在canvas显示的区域 - mDestRect.right = dis; - canvas.drawBitmap(mNextBitmap,0,0,null); - canvas.drawBitmap(mCurBitmap,mSrcRect,mDestRect,null); - addShadow(dis,canvas); - break; - default: - mSrcRect.left = (int) (mViewWidth - mTouchX); - mDestRect.right = (int) mTouchX; - canvas.drawBitmap(mCurBitmap,0,0,null); - canvas.drawBitmap(mNextBitmap,mSrcRect,mDestRect,null); - addShadow((int) mTouchX,canvas); - break; - } - } - - //添加阴影 - public void addShadow(int left, Canvas canvas) { - mBackShadowDrawableLR.setBounds(left, 0, left + 30 , mScreenHeight); - mBackShadowDrawableLR.draw(canvas); - } - - @Override - public void startAnim() { - super.startAnim(); - int dx = 0; - switch (mDirection){ - case NEXT: - if (isCancel){ - int dis = (int) ((mViewWidth - mStartX) + mTouchX); - if (dis > mViewWidth){ - dis = mViewWidth; - } - dx = mViewWidth - dis; - }else{ - dx = (int) -(mTouchX + (mViewWidth - mStartX)); - } - break; - default: - if (isCancel){ - dx = (int) -mTouchX; - }else{ - dx = (int) (mViewWidth - mTouchX); - } - break; - } - - //滑动速度保持一致 - int duration = (400 * Math.abs(dx)) / mViewWidth; - mScroller.startScroll((int) mTouchX, 0, dx, 0, duration); - } -} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.kt b/app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.kt new file mode 100644 index 0000000..2a2795c --- /dev/null +++ b/app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.kt @@ -0,0 +1,97 @@ +package com.novel.read.widget.page.anim + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Rect +import android.graphics.drawable.GradientDrawable +import android.view.View +import com.novel.read.widget.page.PageAnimation + +/** + * Created by zlj + * 覆盖动画 + */ + +class CoverPageAnim(w: Int, h: Int, view: View, listener: PageAnimation.OnPageChangeListener) : + HorizonPageAnim(w, h, view, listener) { + + private val mSrcRect: Rect + private val mDestRect: Rect + private val mBackShadowDrawableLR: GradientDrawable + + init { + mSrcRect = Rect(0, 0, mViewWidth, mViewHeight) + mDestRect = Rect(0, 0, mViewWidth, mViewHeight) + val mBackShadowColors = intArrayOf(0x66000000, 0x00000000) + mBackShadowDrawableLR = GradientDrawable( + GradientDrawable.Orientation.LEFT_RIGHT, mBackShadowColors + ) + mBackShadowDrawableLR.gradientType = GradientDrawable.LINEAR_GRADIENT + } + + override fun drawStatic(canvas: Canvas) { + if (isCancel) { + mNextBitmap = mCurBitmap.copy(Bitmap.Config.RGB_565, true) + canvas.drawBitmap(mCurBitmap, 0f, 0f, null) + } else { + canvas.drawBitmap(mNextBitmap, 0f, 0f, null) + } + } + + override fun drawMove(canvas: Canvas) { + + when (mDirection) { + PageAnimation.Direction.NEXT -> { + var dis = (mViewWidth - mStartX + mTouchX).toInt() + if (dis > mViewWidth) { + dis = mViewWidth + } + //计算bitmap截取的区域 + mSrcRect.left = mViewWidth - dis + //计算bitmap在canvas显示的区域 + mDestRect.right = dis + canvas.drawBitmap(mNextBitmap, 0f, 0f, null) + canvas.drawBitmap(mCurBitmap, mSrcRect, mDestRect, null) + addShadow(dis, canvas) + } + else -> { + mSrcRect.left = (mViewWidth - mTouchX).toInt() + mDestRect.right = mTouchX.toInt() + canvas.drawBitmap(mCurBitmap, 0f, 0f, null) + canvas.drawBitmap(mNextBitmap, mSrcRect, mDestRect, null) + addShadow(mTouchX.toInt(), canvas) + } + } + } + + //添加阴影 + fun addShadow(left: Int, canvas: Canvas) { + mBackShadowDrawableLR.setBounds(left, 0, left + 30, mScreenHeight) + mBackShadowDrawableLR.draw(canvas) + } + + override fun startAnim() { + super.startAnim() + var dx = 0 + when (mDirection) { + PageAnimation.Direction.NEXT -> if (isCancel) { + var dis = (mViewWidth - mStartX + mTouchX).toInt() + if (dis > mViewWidth) { + dis = mViewWidth + } + dx = mViewWidth - dis + } else { + dx = (-(mTouchX + (mViewWidth - mStartX))).toInt() + } + else -> if (isCancel) { + dx = (-mTouchX).toInt() + } else { + dx = (mViewWidth - mTouchX).toInt() + } + } + + //滑动速度保持一致 + val duration = 400 * Math.abs(dx) / mViewWidth + mScroller.startScroll(mTouchX.toInt(), 0, dx, 0, duration) + } +} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.java b/app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.java deleted file mode 100644 index 630e6b9..0000000 --- a/app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.java +++ /dev/null @@ -1,38 +0,0 @@ -package com.novel.read.widget.page.anim; - -import android.graphics.Canvas; -import android.view.View; - -/** - * Created by zlj - * 无 - */ - -public class NonePageAnim extends HorizonPageAnim{ - - public NonePageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - } - - @Override - public void drawStatic(Canvas canvas) { - if (isCancel){ - canvas.drawBitmap(mCurBitmap, 0, 0, null); - }else { - canvas.drawBitmap(mNextBitmap, 0, 0, null); - } - } - - @Override - public void drawMove(Canvas canvas) { - if (isCancel){ - canvas.drawBitmap(mCurBitmap, 0, 0, null); - }else { - canvas.drawBitmap(mNextBitmap, 0, 0, null); - } - } - - @Override - public void startAnim() { - } -} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.kt b/app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.kt new file mode 100644 index 0000000..f574eb7 --- /dev/null +++ b/app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.kt @@ -0,0 +1,32 @@ +package com.novel.read.widget.page.anim + +import android.graphics.Canvas +import android.view.View +import com.novel.read.widget.page.PageAnimation + +/** + * Created by zlj + * 无 + */ + +class NonePageAnim(w: Int, h: Int, view: View, listener: PageAnimation.OnPageChangeListener) : + HorizonPageAnim(w, h, view, listener) { + + override fun drawStatic(canvas: Canvas) { + if (isCancel) { + canvas.drawBitmap(mCurBitmap, 0f, 0f, null) + } else { + canvas.drawBitmap(mNextBitmap, 0f, 0f, null) + } + } + + override fun drawMove(canvas: Canvas) { + if (isCancel) { + canvas.drawBitmap(mCurBitmap, 0f, 0f, null) + } else { + canvas.drawBitmap(mNextBitmap, 0f, 0f, null) + } + } + + override fun startAnim() {} +} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.java b/app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.java deleted file mode 100644 index da8f47c..0000000 --- a/app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.java +++ /dev/null @@ -1,408 +0,0 @@ -package com.novel.read.widget.page.anim; - -import android.graphics.Bitmap; -import android.graphics.Canvas; -import android.graphics.Rect; -import android.view.MotionEvent; -import android.view.VelocityTracker; -import android.view.View; - -import com.novel.read.widget.page.PageAnimation; - -import java.util.ArrayDeque; -import java.util.ArrayList; -import java.util.Iterator; - -/** - * Created by zlj - * 原理:仿照ListView源码实现的上下滑动效果 - * 问题: - * 1. 向上翻页,重复的问题 (完成) - * 2. 滑动卡顿的问题。原因:由于绘制的数据过多造成的卡顿问题。 (主要是文字绘制需要的时长比较多) 解决办法:做文字缓冲 - * 3. 弱网环境下,显示的问题 - */ -public class ScrollPageAnim extends PageAnimation { - private static final String TAG = "ScrollAnimation"; - // 滑动追踪的时间 - private static final int VELOCITY_DURATION = 1000; - private VelocityTracker mVelocity; - - // 整个Bitmap的背景显示 - private Bitmap mBgBitmap; - - // 下一个展示的图片 - private Bitmap mNextBitmap; - - // 被废弃的图片列表 - private ArrayDeque mScrapViews; - // 正在被利用的图片列表 - private ArrayList mActiveViews = new ArrayList<>(2); - - // 是否处于刷新阶段 - private boolean isRefresh = true; - - public ScrollPageAnim(int w, int h, int marginWidth, int marginHeight, - View view, OnPageChangeListener listener) { - super(w, h, marginWidth, marginHeight, view, listener); - // 创建两个BitmapView - initWidget(); - } - - private void initWidget() { - mBgBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565); - - mScrapViews = new ArrayDeque<>(2); - for (int i = 0; i < 2; ++i) { - BitmapView view = new BitmapView(); - view.bitmap = Bitmap.createBitmap(mViewWidth, mViewHeight, Bitmap.Config.RGB_565); - view.srcRect = new Rect(0, 0, mViewWidth, mViewHeight); - view.destRect = new Rect(0, 0, mViewWidth, mViewHeight); - view.top = 0; - view.bottom = view.bitmap.getHeight(); - - mScrapViews.push(view); - } - onLayout(); - isRefresh = false; - } - - // 修改布局,填充内容 - private void onLayout() { - // 如果还没有开始加载,则从上到下进行绘制 - if (mActiveViews.size() == 0) { - fillDown(0, 0); - mDirection = Direction.NONE; - } else { - int offset = (int) (mTouchY - mLastY); - // 判断是下滑还是上拉 (下滑) - if (offset > 0) { - int topEdge = mActiveViews.get(0).top; - fillUp(topEdge, offset); - } - // 上拉 - else { - // 底部的距离 = 当前底部的距离 + 滑动的距离 (因为上滑,得到的值肯定是负的) - int bottomEdge = mActiveViews.get(mActiveViews.size() - 1).bottom; - fillDown(bottomEdge, offset); - } - } - } - - // 底部填充 - private Iterator downIt; - - /** - * 创建View填充底部空白部分 - * - * @param bottomEdge :当前最后一个View的底部,在整个屏幕上的位置,即相对于屏幕顶部的距离 - * @param offset :滑动的偏移量 - */ - private void fillDown(int bottomEdge, int offset) { - - downIt = mActiveViews.iterator(); - BitmapView view; - - // 进行删除 - while (downIt.hasNext()) { - view = downIt.next(); - view.top = view.top + offset; - view.bottom = view.bottom + offset; - // 设置允许显示的范围 - view.destRect.top = view.top; - view.destRect.bottom = view.bottom; - - // 判断是否越界了 - if (view.bottom <= 0) { - // 添加到废弃的View中 - mScrapViews.add(view); - // 从Active中移除 - downIt.remove(); - // 如果原先是从上加载,现在变成从下加载,则表示取消 - if (mDirection == Direction.UP) { - mListener.pageCancel(); - mDirection = Direction.NONE; - } - } - } - - // 滑动之后的最后一个 View 的距离屏幕顶部上的实际位置 - int realEdge = bottomEdge + offset; - - // 进行填充 - while (realEdge < mViewHeight && mActiveViews.size() < 2) { - // 从废弃的Views中获取一个 - view = mScrapViews.getFirst(); -/* //擦除其Bitmap(重新创建会不会更好一点) - eraseBitmap(view.bitmap,view.bitmap.getWidth(),view.bitmap.getHeight(),0,0);*/ - if (view == null) return; - - Bitmap cancelBitmap = mNextBitmap; - mNextBitmap = view.bitmap; - - if (!isRefresh) { - boolean hasNext = mListener.hasNext(); //如果不成功则无法滑动 - - // 如果不存在next,则进行还原 - if (!hasNext) { - mNextBitmap = cancelBitmap; - for (BitmapView activeView : mActiveViews) { - activeView.top = 0; - activeView.bottom = mViewHeight; - // 设置允许显示的范围 - activeView.destRect.top = activeView.top; - activeView.destRect.bottom = activeView.bottom; - } - abortAnim(); - return; - } - } - - // 如果加载成功,那么就将View从ScrapViews中移除 - mScrapViews.removeFirst(); - // 添加到存活的Bitmap中 - mActiveViews.add(view); - mDirection = Direction.DOWN; - - // 设置Bitmap的范围 - view.top = realEdge; - view.bottom = realEdge + view.bitmap.getHeight(); - // 设置允许显示的范围 - view.destRect.top = view.top; - view.destRect.bottom = view.bottom; - - realEdge += view.bitmap.getHeight(); - } - } - - private Iterator upIt; - - /** - * 创建View填充顶部空白部分 - * - * @param topEdge : 当前第一个View的顶部,到屏幕顶部的距离 - * @param offset : 滑动的偏移量 - */ - private void fillUp(int topEdge, int offset) { - // 首先进行布局的调整 - upIt = mActiveViews.iterator(); - BitmapView view; - while (upIt.hasNext()) { - view = upIt.next(); - view.top = view.top + offset; - view.bottom = view.bottom + offset; - //设置允许显示的范围 - view.destRect.top = view.top; - view.destRect.bottom = view.bottom; - - // 判断是否越界了 - if (view.top >= mViewHeight) { - // 添加到废弃的View中 - mScrapViews.add(view); - // 从Active中移除 - upIt.remove(); - - // 如果原先是下,现在变成从上加载了,则表示取消加载 - - if (mDirection == Direction.DOWN) { - mListener.pageCancel(); - mDirection = Direction.NONE; - } - } - } - - // 滑动之后,第一个 View 的顶部距离屏幕顶部的实际位置。 - int realEdge = topEdge + offset; - - // 对布局进行View填充 - while (realEdge > 0 && mActiveViews.size() < 2) { - // 从废弃的Views中获取一个 - view = mScrapViews.getFirst(); - if (view == null) return; - - // 判断是否存在上一章节 - Bitmap cancelBitmap = mNextBitmap; - mNextBitmap = view.bitmap; - if (!isRefresh) { - boolean hasPrev = mListener.hasPrev(); // 如果不成功则无法滑动 - // 如果不存在next,则进行还原 - if (!hasPrev) { - mNextBitmap = cancelBitmap; - for (BitmapView activeView : mActiveViews) { - activeView.top = 0; - activeView.bottom = mViewHeight; - // 设置允许显示的范围 - activeView.destRect.top = activeView.top; - activeView.destRect.bottom = activeView.bottom; - } - abortAnim(); - return; - } - } - // 如果加载成功,那么就将View从ScrapViews中移除 - mScrapViews.removeFirst(); - // 加入到存活的对象中 - mActiveViews.add(0, view); - mDirection = Direction.UP; - // 设置Bitmap的范围 - view.top = realEdge - view.bitmap.getHeight(); - view.bottom = realEdge; - - // 设置允许显示的范围 - view.destRect.top = view.top; - view.destRect.bottom = view.bottom; - realEdge -= view.bitmap.getHeight(); - } - } - - /** - * 对Bitmap进行擦除 - * - * @param b - * @param width - * @param height - * @param paddingLeft - * @param paddingTop - */ - private void eraseBitmap(Bitmap b, int width, int height, - int paddingLeft, int paddingTop) { - /* if (mInitBitmapPix == null) return; - b.setPixels(mInitBitmapPix, 0, width, paddingLeft, paddingTop, width, height);*/ - } - - /** - * 重置位移 - */ - public void resetBitmap() { - isRefresh = true; - // 将所有的Active加入到Scrap中 - for (BitmapView view : mActiveViews) { - mScrapViews.add(view); - } - // 清除所有的Active - mActiveViews.clear(); - // 重新进行布局 - onLayout(); - isRefresh = false; - } - - @Override - public boolean onTouchEvent(MotionEvent event) { - int x = (int) event.getX(); - int y = (int) event.getY(); - - // 初始化速度追踪器 - if (mVelocity == null) { - mVelocity = VelocityTracker.obtain(); - } - - mVelocity.addMovement(event); - // 设置触碰点 - setTouchPoint(x, y); - - switch (event.getAction()) { - case MotionEvent.ACTION_DOWN: - isRunning = false; - // 设置起始点 - setStartPoint(x, y); - // 停止动画 - abortAnim(); - break; - case MotionEvent.ACTION_MOVE: - mVelocity.computeCurrentVelocity(VELOCITY_DURATION); - isRunning = true; - // 进行刷新 - mView.postInvalidate(); - break; - case MotionEvent.ACTION_UP: - isRunning = false; - // 开启动画 - startAnim(); - // 删除检测器 - mVelocity.recycle(); - mVelocity = null; - break; - - case MotionEvent.ACTION_CANCEL: - try { - mVelocity.recycle(); // if velocityTracker won't be used should be recycled - mVelocity = null; - } catch (Exception e) { - e.printStackTrace(); - } - break; - } - return true; - } - - - BitmapView tmpView; - - @Override - public void draw(Canvas canvas) { - //进行布局 - onLayout(); - - //绘制背景 - canvas.drawBitmap(mBgBitmap, 0, 0, null); - //绘制内容 - canvas.save(); - //移动位置 - canvas.translate(0, mMarginHeight); - //裁剪显示区域 - canvas.clipRect(0, 0, mViewWidth, mViewHeight); -/* //设置背景透明 - canvas.drawColor(0x40);*/ - //绘制Bitmap - for (int i = 0; i < mActiveViews.size(); ++i) { - tmpView = mActiveViews.get(i); - canvas.drawBitmap(tmpView.bitmap, tmpView.srcRect, tmpView.destRect, null); - } - canvas.restore(); - } - - @Override - public synchronized void startAnim() { - isRunning = true; - mScroller.fling(0, (int) mTouchY, 0, (int) mVelocity.getYVelocity() - , 0, 0, Integer.MAX_VALUE * -1, Integer.MAX_VALUE); - } - - @Override - public void scrollAnim() { - if (mScroller.computeScrollOffset()) { - int x = mScroller.getCurrX(); - int y = mScroller.getCurrY(); - setTouchPoint(x, y); - if (mScroller.getFinalX() == x && mScroller.getFinalY() == y) { - isRunning = false; - } - mView.postInvalidate(); - } - } - - @Override - public void abortAnim() { - if (!mScroller.isFinished()) { - mScroller.abortAnimation(); - isRunning = false; - } - } - - @Override - public Bitmap getBgBitmap() { - return mBgBitmap; - } - - @Override - public Bitmap getNextBitmap() { - return mNextBitmap; - } - - private static class BitmapView { - Bitmap bitmap; - Rect srcRect; - Rect destRect; - int top; - int bottom; - } -} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.kt b/app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.kt new file mode 100644 index 0000000..453ad2e --- /dev/null +++ b/app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.kt @@ -0,0 +1,412 @@ +package com.novel.read.widget.page.anim + +import android.graphics.Bitmap +import android.graphics.Canvas +import android.graphics.Rect +import android.view.MotionEvent +import android.view.VelocityTracker +import android.view.View + +import com.novel.read.widget.page.PageAnimation + +import java.util.ArrayDeque +import java.util.ArrayList + +/** + * Created by zlj + * 原理:仿照ListView源码实现的上下滑动效果 + * 问题: + * 1. 向上翻页,重复的问题 (完成) + * 2. 滑动卡顿的问题。原因:由于绘制的数据过多造成的卡顿问题。 (主要是文字绘制需要的时长比较多) 解决办法:做文字缓冲 + * 3. 弱网环境下,显示的问题 + */ +class ScrollPageAnim( + w: Int, h: Int, marginWidth: Int, marginHeight: Int, + view: View, listener: PageAnimation.OnPageChangeListener +) : PageAnimation(w, h, marginWidth, marginHeight, view, listener) { + private var mVelocity: VelocityTracker? = null + + // 整个Bitmap的背景显示 + private var mBgBitmap: Bitmap? = null + + // 下一个展示的图片 + private var mNextBitmap: Bitmap? = null + + // 被废弃的图片列表 + private var mScrapViews: ArrayDeque? = null + // 正在被利用的图片列表 + private val mActiveViews = ArrayList(2) + + // 是否处于刷新阶段 + private var isRefresh = true + + // 底部填充 + private var downIt: MutableIterator? = null + + private var upIt: MutableIterator? = null + + + private var tmpView: BitmapView? = null + + init { + // 创建两个BitmapView + initWidget() + } + + private fun initWidget() { + mBgBitmap = Bitmap.createBitmap(mScreenWidth, mScreenHeight, Bitmap.Config.RGB_565) + + mScrapViews = ArrayDeque(2) + for (i in 0..1) { + val view = BitmapView() + view.bitmap = Bitmap.createBitmap(mViewWidth, mViewHeight, Bitmap.Config.RGB_565) + view.srcRect = Rect(0, 0, mViewWidth, mViewHeight) + view.destRect = Rect(0, 0, mViewWidth, mViewHeight) + view.top = 0 + view.bottom = view.bitmap!!.height + + mScrapViews!!.push(view) + } + onLayout() + isRefresh = false + } + + // 修改布局,填充内容 + private fun onLayout() { + // 如果还没有开始加载,则从上到下进行绘制 + if (mActiveViews.size == 0) { + fillDown(0, 0) + mDirection = PageAnimation.Direction.NONE + } else { + val offset = (mTouchY - mLastY).toInt() + // 判断是下滑还是上拉 (下滑) + if (offset > 0) { + val topEdge = mActiveViews[0].top + fillUp(topEdge, offset) + } else { + // 底部的距离 = 当前底部的距离 + 滑动的距离 (因为上滑,得到的值肯定是负的) + val bottomEdge = mActiveViews[mActiveViews.size - 1].bottom + fillDown(bottomEdge, offset) + }// 上拉 + } + } + + /** + * 创建View填充底部空白部分 + * + * @param bottomEdge :当前最后一个View的底部,在整个屏幕上的位置,即相对于屏幕顶部的距离 + * @param offset :滑动的偏移量 + */ + private fun fillDown(bottomEdge: Int, offset: Int) { + + downIt = mActiveViews.iterator() + var view: BitmapView? + + // 进行删除 + while (downIt!!.hasNext()) { + view = downIt!!.next() + view.top = view.top + offset + view.bottom = view.bottom + offset + // 设置允许显示的范围 + view.destRect!!.top = view.top + view.destRect!!.bottom = view.bottom + + // 判断是否越界了 + if (view.bottom <= 0) { + // 添加到废弃的View中 + mScrapViews!!.add(view) + // 从Active中移除 + downIt!!.remove() + // 如果原先是从上加载,现在变成从下加载,则表示取消 + if (mDirection == PageAnimation.Direction.UP) { + mListener.pageCancel() + mDirection = PageAnimation.Direction.NONE + } + } + } + + // 滑动之后的最后一个 View 的距离屏幕顶部上的实际位置 + var realEdge = bottomEdge + offset + + // 进行填充 + while (realEdge < mViewHeight && mActiveViews.size < 2) { + // 从废弃的Views中获取一个 + view = mScrapViews!!.first + /* //擦除其Bitmap(重新创建会不会更好一点) + eraseBitmap(view.bitmap,view.bitmap.getWidth(),view.bitmap.getHeight(),0,0);*/ + if (view == null) return + + val cancelBitmap = mNextBitmap + mNextBitmap = view.bitmap + + if (!isRefresh) { + val hasNext = mListener.hasNext() //如果不成功则无法滑动 + + // 如果不存在next,则进行还原 + if (!hasNext) { + mNextBitmap = cancelBitmap + for (activeView in mActiveViews) { + activeView.top = 0 + activeView.bottom = mViewHeight + // 设置允许显示的范围 + activeView.destRect!!.top = activeView.top + activeView.destRect!!.bottom = activeView.bottom + } + abortAnim() + return + } + } + + // 如果加载成功,那么就将View从ScrapViews中移除 + mScrapViews!!.removeFirst() + // 添加到存活的Bitmap中 + mActiveViews.add(view) + mDirection = PageAnimation.Direction.DOWN + + // 设置Bitmap的范围 + view.top = realEdge + view.bottom = realEdge + view.bitmap!!.height + // 设置允许显示的范围 + view.destRect!!.top = view.top + view.destRect!!.bottom = view.bottom + + realEdge += view.bitmap!!.height + } + } + + /** + * 创建View填充顶部空白部分 + * + * @param topEdge : 当前第一个View的顶部,到屏幕顶部的距离 + * @param offset : 滑动的偏移量 + */ + private fun fillUp(topEdge: Int, offset: Int) { + // 首先进行布局的调整 + upIt = mActiveViews.iterator() + var view: BitmapView? + while (upIt!!.hasNext()) { + view = upIt!!.next() + view.top = view.top + offset + view.bottom = view.bottom + offset + //设置允许显示的范围 + view.destRect!!.top = view.top + view.destRect!!.bottom = view.bottom + + // 判断是否越界了 + if (view.top >= mViewHeight) { + // 添加到废弃的View中 + mScrapViews!!.add(view) + // 从Active中移除 + upIt!!.remove() + + // 如果原先是下,现在变成从上加载了,则表示取消加载 + + if (mDirection == PageAnimation.Direction.DOWN) { + mListener.pageCancel() + mDirection = PageAnimation.Direction.NONE + } + } + } + + // 滑动之后,第一个 View 的顶部距离屏幕顶部的实际位置。 + var realEdge = topEdge + offset + + // 对布局进行View填充 + while (realEdge > 0 && mActiveViews.size < 2) { + // 从废弃的Views中获取一个 + view = mScrapViews!!.first + if (view == null) return + + // 判断是否存在上一章节 + val cancelBitmap = mNextBitmap + mNextBitmap = view.bitmap + if (!isRefresh) { + val hasPrev = mListener.hasPrev() // 如果不成功则无法滑动 + // 如果不存在next,则进行还原 + if (!hasPrev) { + mNextBitmap = cancelBitmap + for (activeView in mActiveViews) { + activeView.top = 0 + activeView.bottom = mViewHeight + // 设置允许显示的范围 + activeView.destRect!!.top = activeView.top + activeView.destRect!!.bottom = activeView.bottom + } + abortAnim() + return + } + } + // 如果加载成功,那么就将View从ScrapViews中移除 + mScrapViews!!.removeFirst() + // 加入到存活的对象中 + mActiveViews.add(0, view) + mDirection = PageAnimation.Direction.UP + // 设置Bitmap的范围 + view.top = realEdge - view.bitmap!!.height + view.bottom = realEdge + + // 设置允许显示的范围 + view.destRect!!.top = view.top + view.destRect!!.bottom = view.bottom + realEdge -= view.bitmap!!.height + } + } + + /** + * 对Bitmap进行擦除 + * + * @param b + * @param width + * @param height + * @param paddingLeft + * @param paddingTop + */ + private fun eraseBitmap( + b: Bitmap, width: Int, height: Int, + paddingLeft: Int, paddingTop: Int + ) { + /* if (mInitBitmapPix == null) return; + b.setPixels(mInitBitmapPix, 0, width, paddingLeft, paddingTop, width, height);*/ + } + + /** + * 重置位移 + */ + fun resetBitmap() { + isRefresh = true + // 将所有的Active加入到Scrap中 + for (view in mActiveViews) { + mScrapViews!!.add(view) + } + // 清除所有的Active + mActiveViews.clear() + // 重新进行布局 + onLayout() + isRefresh = false + } + + override fun onTouchEvent(event: MotionEvent): Boolean { + val x = event.x.toInt() + val y = event.y.toInt() + + // 初始化速度追踪器 + if (mVelocity == null) { + mVelocity = VelocityTracker.obtain() + } + + mVelocity!!.addMovement(event) + // 设置触碰点 + setTouchPoint(x.toFloat(), y.toFloat()) + + when (event.action) { + MotionEvent.ACTION_DOWN -> { + isRunning = false + // 设置起始点 + setStartPoint(x.toFloat(), y.toFloat()) + // 停止动画 + abortAnim() + } + MotionEvent.ACTION_MOVE -> { + mVelocity!!.computeCurrentVelocity(VELOCITY_DURATION) + isRunning = true + // 进行刷新 + mView.postInvalidate() + } + MotionEvent.ACTION_UP -> { + isRunning = false + // 开启动画 + startAnim() + // 删除检测器 + mVelocity!!.recycle() + mVelocity = null + } + + MotionEvent.ACTION_CANCEL -> try { + mVelocity!!.recycle() // if velocityTracker won't be used should be recycled + mVelocity = null + } catch (e: Exception) { + e.printStackTrace() + } + + } + return true + } + + override fun draw(canvas: Canvas) { + //进行布局 + onLayout() + + //绘制背景 + canvas.drawBitmap(mBgBitmap!!, 0f, 0f, null) + //绘制内容 + canvas.save() + //移动位置 + canvas.translate(0f, mMarginHeight.toFloat()) + //裁剪显示区域 + canvas.clipRect(0, 0, mViewWidth, mViewHeight) + /* //设置背景透明 + canvas.drawColor(0x40);*/ + //绘制Bitmap + for (i in mActiveViews.indices) { + tmpView = mActiveViews[i] + canvas.drawBitmap(tmpView!!.bitmap!!, tmpView!!.srcRect, tmpView!!.destRect!!, null) + } + canvas.restore() + } + + @Synchronized + override fun startAnim() { + isRunning = true + mScroller.fling( + 0, + mTouchY.toInt(), + 0, + mVelocity!!.yVelocity.toInt(), + 0, + 0, + Integer.MAX_VALUE * -1, + Integer.MAX_VALUE + ) + } + + override fun scrollAnim() { + if (mScroller.computeScrollOffset()) { + val x = mScroller.currX + val y = mScroller.currY + setTouchPoint(x.toFloat(), y.toFloat()) + if (mScroller.finalX == x && mScroller.finalY == y) { + isRunning = false + } + mView.postInvalidate() + } + } + + override fun abortAnim() { + if (!mScroller.isFinished) { + mScroller.abortAnimation() + isRunning = false + } + } + + override fun getBgBitmap(): Bitmap? { + return mBgBitmap + } + + override fun getNextBitmap(): Bitmap? { + return mNextBitmap + } + + private class BitmapView { + internal var bitmap: Bitmap? = null + internal var srcRect: Rect? = null + internal var destRect: Rect? = null + internal var top: Int = 0 + internal var bottom: Int = 0 + } + + companion object { + private val TAG = "ScrollAnimation" + // 滑动追踪的时间 + private val VELOCITY_DURATION = 1000 + } +} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/SimulationPageAnim.java b/app/src/main/java/com/novel/read/widget/page/anim/SimulationPageAnim.java index 6f61405..9043830 100644 --- a/app/src/main/java/com/novel/read/widget/page/anim/SimulationPageAnim.java +++ b/app/src/main/java/com/novel/read/widget/page/anim/SimulationPageAnim.java @@ -47,17 +47,17 @@ public class SimulationPageAnim extends HorizonPageAnim { boolean mIsRTandLB; // 是否属于右上左下 private float mMaxLength ; - int[] mBackShadowColors;// 背面颜色组 - int[] mFrontShadowColors;// 前面颜色组 - GradientDrawable mBackShadowDrawableLR; // 有阴影的GradientDrawable - GradientDrawable mBackShadowDrawableRL; - GradientDrawable mFolderShadowDrawableLR; - GradientDrawable mFolderShadowDrawableRL; - - GradientDrawable mFrontShadowDrawableHBT; - GradientDrawable mFrontShadowDrawableHTB; - GradientDrawable mFrontShadowDrawableVLR; - GradientDrawable mFrontShadowDrawableVRL; + private int[] mBackShadowColors;// 背面颜色组 + private int[] mFrontShadowColors;// 前面颜色组 + private GradientDrawable mBackShadowDrawableLR; // 有阴影的GradientDrawable + private GradientDrawable mBackShadowDrawableRL; + private GradientDrawable mFolderShadowDrawableLR; + private GradientDrawable mFolderShadowDrawableRL; + + private GradientDrawable mFrontShadowDrawableHBT; + private GradientDrawable mFrontShadowDrawableHTB; + private GradientDrawable mFrontShadowDrawableVLR; + private GradientDrawable mFrontShadowDrawableVRL; Paint mPaint; public SimulationPageAnim(int w, int h, View view, OnPageChangeListener listener) { diff --git a/app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.java b/app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.java deleted file mode 100644 index 48bf949..0000000 --- a/app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.java +++ /dev/null @@ -1,101 +0,0 @@ -package com.novel.read.widget.page.anim; - -import android.graphics.Canvas; -import android.graphics.Rect; -import android.view.View; - -/** - * Created by zlj - */ - -public class SlidePageAnim extends HorizonPageAnim { - private Rect mSrcRect, mDestRect,mNextSrcRect,mNextDestRect; - - public SlidePageAnim(int w, int h, View view, OnPageChangeListener listener) { - super(w, h, view, listener); - mSrcRect = new Rect(0, 0, mViewWidth, mViewHeight); - mDestRect = new Rect(0, 0, mViewWidth, mViewHeight); - mNextSrcRect = new Rect(0, 0, mViewWidth, mViewHeight); - mNextDestRect = new Rect(0, 0, mViewWidth, mViewHeight); - } - - @Override - public void drawStatic(Canvas canvas) { - if (isCancel){ - canvas.drawBitmap(mCurBitmap, 0, 0, null); - }else { - canvas.drawBitmap(mNextBitmap, 0, 0, null); - } - } - - @Override - public void drawMove(Canvas canvas) { - int dis = 0; - switch (mDirection){ - case NEXT: - //左半边的剩余区域 - dis = (int) (mScreenWidth - mStartX + mTouchX); - if (dis > mScreenWidth){ - dis = mScreenWidth; - } - //计算bitmap截取的区域 - mSrcRect.left = mScreenWidth - dis; - //计算bitmap在canvas显示的区域 - mDestRect.right = dis; - //计算下一页截取的区域 - mNextSrcRect.right = mScreenWidth - dis; - //计算下一页在canvas显示的区域 - mNextDestRect.left = dis; - - canvas.drawBitmap(mNextBitmap,mNextSrcRect,mNextDestRect,null); - canvas.drawBitmap(mCurBitmap,mSrcRect,mDestRect,null); - break; - default: - dis = (int) (mTouchX - mStartX); - if (dis < 0){ - dis = 0; - mStartX = mTouchX; - } - mSrcRect.left = mScreenWidth - dis; - mDestRect.right = dis; - - //计算下一页截取的区域 - mNextSrcRect.right = mScreenWidth - dis; - //计算下一页在canvas显示的区域 - mNextDestRect.left = dis; - - canvas.drawBitmap(mCurBitmap,mNextSrcRect,mNextDestRect,null); - canvas.drawBitmap(mNextBitmap,mSrcRect,mDestRect,null); - break; - } - } - - @Override - public void startAnim() { - super.startAnim(); - int dx = 0; - switch (mDirection){ - case NEXT: - if (isCancel){ - int dis = (int)((mScreenWidth - mStartX) + mTouchX); - if (dis > mScreenWidth){ - dis = mScreenWidth; - } - dx = mScreenWidth - dis; - }else{ - dx = (int) -(mTouchX + (mScreenWidth - mStartX)); - } - break; - default: - if (isCancel){ - dx = (int)-Math.abs(mTouchX - mStartX); - }else{ - dx = (int) (mScreenWidth - (mTouchX - mStartX)); - } - break; - } - //滑动速度保持一致 - int duration = (400 * Math.abs(dx)) / mScreenWidth; - mScroller.startScroll((int) mTouchX, 0, dx, 0, duration); - } -} diff --git a/app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.kt b/app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.kt new file mode 100644 index 0000000..d9a01cf --- /dev/null +++ b/app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.kt @@ -0,0 +1,92 @@ +package com.novel.read.widget.page.anim + +import android.graphics.Canvas +import android.graphics.Rect +import android.view.View +import com.novel.read.widget.page.PageAnimation + +/** + * Created by zlj + */ + +class SlidePageAnim(w: Int, h: Int, view: View, listener: PageAnimation.OnPageChangeListener) : + HorizonPageAnim(w, h, view, listener) { + + private val mSrcRect: Rect = Rect(0, 0, mViewWidth, mViewHeight) + private val mDestRect: Rect = Rect(0, 0, mViewWidth, mViewHeight) + private val mNextSrcRect: Rect = Rect(0, 0, mViewWidth, mViewHeight) + private val mNextDestRect: Rect = Rect(0, 0, mViewWidth, mViewHeight) + + override fun drawStatic(canvas: Canvas) { + if (isCancel) { + canvas.drawBitmap(mCurBitmap, 0f, 0f, null) + } else { + canvas.drawBitmap(mNextBitmap, 0f, 0f, null) + } + } + + override fun drawMove(canvas: Canvas) { + var dis = 0 + when (mDirection) { + PageAnimation.Direction.NEXT -> { + //左半边的剩余区域 + dis = (mScreenWidth - mStartX + mTouchX).toInt() + if (dis > mScreenWidth) { + dis = mScreenWidth + } + //计算bitmap截取的区域 + mSrcRect.left = mScreenWidth - dis + //计算bitmap在canvas显示的区域 + mDestRect.right = dis + //计算下一页截取的区域 + mNextSrcRect.right = mScreenWidth - dis + //计算下一页在canvas显示的区域 + mNextDestRect.left = dis + + canvas.drawBitmap(mNextBitmap, mNextSrcRect, mNextDestRect, null) + canvas.drawBitmap(mCurBitmap, mSrcRect, mDestRect, null) + } + else -> { + dis = (mTouchX - mStartX).toInt() + if (dis < 0) { + dis = 0 + mStartX = mTouchX + } + mSrcRect.left = mScreenWidth - dis + mDestRect.right = dis + + //计算下一页截取的区域 + mNextSrcRect.right = mScreenWidth - dis + //计算下一页在canvas显示的区域 + mNextDestRect.left = dis + + canvas.drawBitmap(mCurBitmap, mNextSrcRect, mNextDestRect, null) + canvas.drawBitmap(mNextBitmap, mSrcRect, mDestRect, null) + } + } + } + + override fun startAnim() { + super.startAnim() + var dx = 0 + when (mDirection) { + PageAnimation.Direction.NEXT -> if (isCancel) { + var dis = (mScreenWidth - mStartX + mTouchX).toInt() + if (dis > mScreenWidth) { + dis = mScreenWidth + } + dx = mScreenWidth - dis + } else { + dx = (-(mTouchX + (mScreenWidth - mStartX))).toInt() + } + else -> if (isCancel) { + dx = (-Math.abs(mTouchX - mStartX)).toInt() + } else { + dx = (mScreenWidth - (mTouchX - mStartX)).toInt() + } + } + //滑动速度保持一致 + val duration = 400 * Math.abs(dx) / mScreenWidth + mScroller.startScroll(mTouchX.toInt(), 0, dx, 0, duration) + } +}