转换部分java代码

old
zlj 5 years ago
parent 9a8a88944a
commit 9be6d925eb
  1. 2
      .idea/misc.xml
  2. 13
      app/src/main/java/com/novel/read/activity/NovelSearchActivity.kt
  3. 2
      app/src/main/java/com/novel/read/utlis/Charset.java
  4. 166
      app/src/main/java/com/novel/read/utlis/CleanCacheUtils.java
  5. 170
      app/src/main/java/com/novel/read/utlis/CleanCacheUtils.kt
  6. 37
      app/src/main/java/com/novel/read/utlis/DialogUtils.java
  7. 39
      app/src/main/java/com/novel/read/utlis/DialogUtils.kt
  8. 4
      app/src/main/java/com/novel/read/widget/page/PageMode.kt
  9. 35
      app/src/main/java/com/novel/read/widget/page/PageStyle.java
  10. 19
      app/src/main/java/com/novel/read/widget/page/PageStyle.kt
  11. 2
      app/src/main/java/com/novel/read/widget/page/PageView.java
  12. 4
      app/src/main/java/com/novel/read/widget/page/Void.java
  13. 3
      app/src/main/java/com/novel/read/widget/page/Void.kt
  14. 101
      app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.java
  15. 97
      app/src/main/java/com/novel/read/widget/page/anim/CoverPageAnim.kt
  16. 38
      app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.java
  17. 32
      app/src/main/java/com/novel/read/widget/page/anim/NonePageAnim.kt
  18. 408
      app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.java
  19. 412
      app/src/main/java/com/novel/read/widget/page/anim/ScrollPageAnim.kt
  20. 22
      app/src/main/java/com/novel/read/widget/page/anim/SimulationPageAnim.java
  21. 101
      app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.java
  22. 92
      app/src/main/java/com/novel/read/widget/page/anim/SlidePageAnim.kt

@ -10,7 +10,7 @@
<item index="0" class="java.lang.String" itemvalue="com.squareup.otto.Subscribe" />
</list>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">

@ -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 {

@ -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;
}

@ -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) {
}
}
}

@ -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"
}
}
}

@ -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();
}
}

@ -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
}
}
}

@ -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
}

@ -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;
}
}

@ -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)
}

@ -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();
}

@ -1,4 +0,0 @@
package com.novel.read.widget.page;
public final class Void {
}

@ -0,0 +1,3 @@
package com.novel.read.widget.page
class Void

@ -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);
}
}

@ -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)
}
}

@ -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() {
}
}

@ -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() {}
}

@ -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<BitmapView> mScrapViews;
// 正在被利用的图片列表
private ArrayList<BitmapView> 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<BitmapView> 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<BitmapView> 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;
}
}

@ -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<BitmapView>? = null
// 正在被利用的图片列表
private val mActiveViews = ArrayList<BitmapView>(2)
// 是否处于刷新阶段
private var isRefresh = true
// 底部填充
private var downIt: MutableIterator<BitmapView>? = null
private var upIt: MutableIterator<BitmapView>? = 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
}
}

@ -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) {

@ -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);
}
}

@ -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)
}
}
Loading…
Cancel
Save