mirror of
https://github.com/fumiama/copymanga.git
synced 2026-06-28 23:00:28 +08:00
v1.3.2
1. 更改 加载图片占位 2. 修复 重复写入info 3. 更改 长按删除提示语 4. 增加 翻到上一章时置于末页 5. 优化 浏览漫画性能
This commit is contained in:
9
.idea/dictionaries/rumia.xml
generated
Normal file
9
.idea/dictionaries/rumia.xml
generated
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<component name="ProjectDictionaryState">
|
||||||
|
<dictionary name="rumia">
|
||||||
|
<words>
|
||||||
|
<w>cdwn</w>
|
||||||
|
<w>manga</w>
|
||||||
|
<w>rmrf</w>
|
||||||
|
</words>
|
||||||
|
</dictionary>
|
||||||
|
</component>
|
||||||
@@ -11,8 +11,8 @@ android {
|
|||||||
applicationId "top.fumiama.copymanga"
|
applicationId "top.fumiama.copymanga"
|
||||||
minSdkVersion 23
|
minSdkVersion 23
|
||||||
targetSdkVersion 30
|
targetSdkVersion 30
|
||||||
versionCode 9
|
versionCode 10
|
||||||
versionName '1.3.1'
|
versionName '1.3.2'
|
||||||
resConfigs "zh", "zh-rCN"
|
resConfigs "zh", "zh-rCN"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import top.fumiama.copymanga.handler.DlHandler
|
|||||||
import top.fumiama.copymanga.tool.MangaDlTools
|
import top.fumiama.copymanga.tool.MangaDlTools
|
||||||
import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
|
import top.fumiama.copymanga.tool.MangaDlTools.Companion.wmdlt
|
||||||
import top.fumiama.copymanga.tool.ToolsBox
|
import top.fumiama.copymanga.tool.ToolsBox
|
||||||
|
import top.fumiama.copymanga.view.ChapterToggleButton
|
||||||
import top.fumiama.copymanga.view.LazyScrollView
|
import top.fumiama.copymanga.view.LazyScrollView
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.Thread.sleep
|
import java.lang.Thread.sleep
|
||||||
@@ -41,17 +42,14 @@ class DlActivity : Activity() {
|
|||||||
var haveDlStarted = false
|
var haveDlStarted = false
|
||||||
private var btnNumPerRow = 4
|
private var btnNumPerRow = 4
|
||||||
private lateinit var ltbtn: View
|
private lateinit var ltbtn: View
|
||||||
var tbtnlist: List<ToggleButton> = arrayListOf()
|
var tbtnlist: Array<ChapterToggleButton> = arrayOf()
|
||||||
var tbtnUrlList = arrayListOf<String>()
|
|
||||||
private val handler = DlHandler(this, Looper.myLooper()!!)
|
private val handler = DlHandler(this, Looper.myLooper()!!)
|
||||||
private var btnw = 0
|
private var btnw = 0
|
||||||
private var cdwnWidth = 0
|
private var cdwnWidth = 0
|
||||||
private var canDl = false
|
private var canDl = false
|
||||||
private lateinit var toolsBox: ToolsBox
|
private lateinit var toolsBox: ToolsBox
|
||||||
lateinit var mangaDlTools: MangaDlTools
|
private lateinit var mangaDlTools: MangaDlTools
|
||||||
var multiSelect = false
|
var multiSelect = false
|
||||||
private var zipArrayList: Array<String> = arrayOf()
|
|
||||||
|
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@@ -85,14 +83,14 @@ class DlActivity : Activity() {
|
|||||||
|
|
||||||
private fun fillChapters() {
|
private fun fillChapters() {
|
||||||
mangaDlTools.allocateChapterUrls(checkedChapter)
|
mangaDlTools.allocateChapterUrls(checkedChapter)
|
||||||
for (i in tbtnlist.indices) {
|
for (i in tbtnlist) {
|
||||||
if (tbtnlist[i].isChecked) mangaDlTools.dlChapterUrl(tbtnUrlList[i])
|
if (i.isChecked) mangaDlTools.dlChapterUrl(i.url.toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun dlThead(dlMethod: (i: ToggleButton) -> Unit) {
|
private fun dlThread(dlMethod: (i: ChapterToggleButton) -> Unit) {
|
||||||
sleep(10000)
|
sleep(10000)
|
||||||
for (i in tbtnlist.listIterator()) {
|
for (i in tbtnlist) {
|
||||||
if (i.isChecked) dlMethod(i)
|
if (i.isChecked) dlMethod(i)
|
||||||
if (!canDl) {
|
if (!canDl) {
|
||||||
checkedChapter -= dldChapter
|
checkedChapter -= dldChapter
|
||||||
@@ -139,7 +137,7 @@ class DlActivity : Activity() {
|
|||||||
handler.sendEmptyMessage(9) //set dl card color to red
|
handler.sendEmptyMessage(9) //set dl card color to red
|
||||||
Toast.makeText(this, "十秒后开始下载...", Toast.LENGTH_SHORT).show()
|
Toast.makeText(this, "十秒后开始下载...", Toast.LENGTH_SHORT).show()
|
||||||
fillChapters()
|
fillChapters()
|
||||||
Thread { dlThead { downloadChapterPages(it) } }.start()
|
Thread { dlThread { downloadChapterPages(it) } }.start()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,6 +155,7 @@ class DlActivity : Activity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun analyzeStructure() {
|
private fun analyzeStructure() {
|
||||||
|
ViewMangaActivity.zipList = arrayOf()
|
||||||
Gson().fromJson(json?.reader(), Array<ComicStructure>::class.java)?.let {
|
Gson().fromJson(json?.reader(), Array<ComicStructure>::class.java)?.let {
|
||||||
for (group in it) {
|
for (group in it) {
|
||||||
val tc = layoutInflater.inflate(R.layout.line_caption, ldwn, false)
|
val tc = layoutInflater.inflate(R.layout.line_caption, ldwn, false)
|
||||||
@@ -182,21 +181,21 @@ class DlActivity : Activity() {
|
|||||||
val mangaHome = File("${getExternalFilesDir("")}/$comicName")
|
val mangaHome = File("${getExternalFilesDir("")}/$comicName")
|
||||||
val jsonFile = File(mangaHome, "info.bin")
|
val jsonFile = File(mangaHome, "info.bin")
|
||||||
if(!mangaHome.exists()) mangaHome.mkdirs()
|
if(!mangaHome.exists()) mangaHome.mkdirs()
|
||||||
json?.let { jsonFile.writeText(it) }
|
if(!(jsonFile.exists() && intent.getBooleanExtra("callFromDlList", false))) json?.let { jsonFile.writeText(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
private fun downloadChapterPages(i: ToggleButton) {
|
private fun downloadChapterPages(i: ChapterToggleButton) {
|
||||||
mangaDlTools.onDownloadedListener =
|
mangaDlTools.onDownloadedListener =
|
||||||
object : MangaDlTools.OnDownloadedListener {
|
object : MangaDlTools.OnDownloadedListener {
|
||||||
override fun handleMessage(succeed: Boolean) {
|
override fun handleMessage(succeed: Boolean) {
|
||||||
handler.obtainMessage(if (succeed) 1 else -1, tbtnlist.indexOf(i), 0)
|
handler.obtainMessage(if (succeed) 1 else -1, i.index, 0)
|
||||||
.sendToTarget()
|
.sendToTarget()
|
||||||
}
|
}
|
||||||
override fun handleMessage(succeed: Boolean, pageNow: Int) {
|
override fun handleMessage(succeed: Boolean, pageNow: Int) {
|
||||||
handler.obtainMessage(
|
handler.obtainMessage(
|
||||||
5,
|
5,
|
||||||
tbtnlist.indexOf(i),
|
i.index,
|
||||||
pageNow,
|
pageNow,
|
||||||
succeed
|
succeed
|
||||||
).sendToTarget()
|
).sendToTarget()
|
||||||
@@ -204,16 +203,18 @@ class DlActivity : Activity() {
|
|||||||
override fun handleMessage(pageNow: Int){
|
override fun handleMessage(pageNow: Int){
|
||||||
handler.obtainMessage(
|
handler.obtainMessage(
|
||||||
10,
|
10,
|
||||||
tbtnlist.indexOf(i),
|
i.index,
|
||||||
pageNow
|
pageNow
|
||||||
).sendToTarget()
|
).sendToTarget()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
i.hash?.let {
|
||||||
mangaDlTools.dlChapterAndPackIntoZip(
|
mangaDlTools.dlChapterAndPackIntoZip(
|
||||||
File("${getExternalFilesDir("")}/$comicName/${i.hint}/${i.textOn}.zip"),
|
File("${getExternalFilesDir("")}/$comicName/${i.hint}/${i.textOn}.zip"),
|
||||||
tbtnUrlList[tbtnlist.indexOf(i)].substringAfterLast("/")
|
it
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
fun addTbtn(title: String, url: String, caption: String) {
|
fun addTbtn(title: String, url: String, caption: String) {
|
||||||
@@ -224,11 +225,12 @@ class DlActivity : Activity() {
|
|||||||
isNewTitle = false
|
isNewTitle = false
|
||||||
}
|
}
|
||||||
val tbv = layoutInflater.inflate(R.layout.button_tbutton, ltbtn.ltbtn, false)
|
val tbv = layoutInflater.inflate(R.layout.button_tbutton, ltbtn.ltbtn, false)
|
||||||
|
tbv.tbtn.index = tbtnlist.size
|
||||||
tbtnlist += tbv.tbtn
|
tbtnlist += tbv.tbtn
|
||||||
|
tbv.tbtn.url = url
|
||||||
tbtncnt++
|
tbtncnt++
|
||||||
tbtnUrlList.add(url)
|
val zipPosition = ViewMangaActivity.zipList?.size
|
||||||
val zipPosition = zipArrayList.size
|
ViewMangaActivity.zipList = ViewMangaActivity.zipList?.plus("$title.zip")
|
||||||
zipArrayList += "$title.zip"
|
|
||||||
tbv.tbtn.textOff = title
|
tbv.tbtn.textOff = title
|
||||||
tbv.tbtn.textOn = title
|
tbv.tbtn.textOn = title
|
||||||
tbv.tbtn.text = title
|
tbv.tbtn.text = title
|
||||||
@@ -251,7 +253,7 @@ class DlActivity : Activity() {
|
|||||||
else tdwn.text = "$dldChapter/${--checkedChapter}"
|
else tdwn.text = "$dldChapter/${--checkedChapter}"
|
||||||
}else if(it.tbtn.isChecked){
|
}else if(it.tbtn.isChecked){
|
||||||
it.tbtn.isChecked = false
|
it.tbtn.isChecked = false
|
||||||
callVM(title, zipf, zipPosition)
|
zipPosition?.let { callVM(title, zipf, it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tbv.tbtn.setOnLongClickListener {
|
tbv.tbtn.setOnLongClickListener {
|
||||||
@@ -289,7 +291,7 @@ class DlActivity : Activity() {
|
|||||||
private fun callVM(titleText: String, zipFile: File, zipPosition:Int){
|
private fun callVM(titleText: String, zipFile: File, zipPosition:Int){
|
||||||
ViewMangaActivity.titleText = titleText
|
ViewMangaActivity.titleText = titleText
|
||||||
ViewMangaActivity.zipFile = zipFile
|
ViewMangaActivity.zipFile = zipFile
|
||||||
ViewMangaActivity.zipList = zipArrayList
|
//ViewMangaActivity.zipList = zipArrayList
|
||||||
ViewMangaActivity.zipPosition = zipPosition
|
ViewMangaActivity.zipPosition = zipPosition
|
||||||
ViewMangaActivity.cd = zipFile.parentFile
|
ViewMangaActivity.cd = zipFile.parentFile
|
||||||
startActivity(Intent(this, ViewMangaActivity::class.java))
|
startActivity(Intent(this, ViewMangaActivity::class.java))
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ class DlListActivity:Activity() {
|
|||||||
ViewMangaActivity.zipFile = chosenFile
|
ViewMangaActivity.zipFile = chosenFile
|
||||||
ViewMangaActivity.titleText = it[position]
|
ViewMangaActivity.titleText = it[position]
|
||||||
ViewMangaActivity.zipPosition = position
|
ViewMangaActivity.zipPosition = position
|
||||||
ViewMangaActivity.zipList = it
|
ViewMangaActivity.zipList = it as Array<String>
|
||||||
ViewMangaActivity.cd = cd
|
ViewMangaActivity.cd = cd
|
||||||
startActivity(Intent(this, ViewMangaActivity::class.java))
|
startActivity(Intent(this, ViewMangaActivity::class.java))
|
||||||
}
|
}
|
||||||
@@ -66,8 +66,8 @@ class DlListActivity:Activity() {
|
|||||||
mylv.setOnItemLongClickListener { _, _, position, _ ->
|
mylv.setOnItemLongClickListener { _, _, position, _ ->
|
||||||
val chosenFile = File(cd, it[position])
|
val chosenFile = File(cd, it[position])
|
||||||
AlertDialog.Builder(this)
|
AlertDialog.Builder(this)
|
||||||
.setIcon(R.drawable.ic_launcher_foreground).setMessage("是否在此执行删除/查错?")
|
.setIcon(R.drawable.ic_launcher_foreground).setMessage("在此执行删除/查错?")
|
||||||
.setTitle("提示").setPositiveButton(android.R.string.ok){ _, _ ->
|
.setTitle("提示").setPositiveButton("删除"){ _, _ ->
|
||||||
if(chosenFile.exists()) handler?.obtainMessage(2, chosenFile)?.sendToTarget() //call rmrf
|
if(chosenFile.exists()) handler?.obtainMessage(2, chosenFile)?.sendToTarget() //call rmrf
|
||||||
handler?.obtainMessage(3, cd)?.sendToTarget() //call scanFile
|
handler?.obtainMessage(3, cd)?.sendToTarget() //call scanFile
|
||||||
}.setNegativeButton(android.R.string.cancel){_, _ ->}
|
}.setNegativeButton(android.R.string.cancel){_, _ ->}
|
||||||
@@ -97,7 +97,10 @@ class DlListActivity:Activity() {
|
|||||||
private fun callDownloadActivity(jsonFile: File){
|
private fun callDownloadActivity(jsonFile: File){
|
||||||
DlActivity.json = jsonFile.readText()
|
DlActivity.json = jsonFile.readText()
|
||||||
DlActivity.comicName = jsonFile.parentFile?.name?:"Null"
|
DlActivity.comicName = jsonFile.parentFile?.name?:"Null"
|
||||||
startActivity(Intent(this, DlActivity::class.java))
|
startActivity(
|
||||||
|
Intent(this, DlActivity::class.java)
|
||||||
|
.putExtra("callFromDlList", true)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findNullWebpZipFileInDir(f: File){
|
private fun findNullWebpZipFileInDir(f: File){
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class MainActivity: Activity() {
|
|||||||
setContentView(R.layout.activity_main)
|
setContentView(R.layout.activity_main)
|
||||||
|
|
||||||
wm = WeakReference(this)
|
wm = WeakReference(this)
|
||||||
mh = MainHandler(Looper.getMainLooper())
|
mh = MainHandler(Looper.myLooper()!!)
|
||||||
toolsBox = ToolsBox(wm as WeakReference<Any>)
|
toolsBox = ToolsBox(wm as WeakReference<Any>)
|
||||||
toolsBox?.netinfo?.let {
|
toolsBox?.netinfo?.let {
|
||||||
if(it == "无网络" || it == "错误"){
|
if(it == "无网络" || it == "错误"){
|
||||||
|
|||||||
@@ -5,10 +5,7 @@ import android.annotation.SuppressLint
|
|||||||
import android.app.Activity
|
import android.app.Activity
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.os.Build
|
import android.os.*
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Message
|
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@@ -105,6 +102,13 @@ class ViewMangaActivity : Activity() {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
prepareItems()
|
prepareItems()
|
||||||
|
if(pn > 0) {
|
||||||
|
pageNum = pn
|
||||||
|
pn = -1
|
||||||
|
}else if(pn == -2){
|
||||||
|
pageNum = count
|
||||||
|
pn = -1
|
||||||
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
toolsBox.toastError("准备控件错误")
|
toolsBox.toastError("准备控件错误")
|
||||||
@@ -152,7 +156,11 @@ class ViewMangaActivity : Activity() {
|
|||||||
|
|
||||||
private fun loadOneImg() {
|
private fun loadOneImg() {
|
||||||
if(dlZip2View) onei.setImageBitmap(getImgBitmap(currentItem))
|
if(dlZip2View) onei.setImageBitmap(getImgBitmap(currentItem))
|
||||||
else Glide.with(this@ViewMangaActivity).load(imgUrls[currentItem]).placeholder(R.drawable.bg_comment).into(onei)
|
else Glide.with(this@ViewMangaActivity)
|
||||||
|
.load(imgUrls[currentItem])
|
||||||
|
.placeholder(R.drawable.ic_dl)
|
||||||
|
.dontAnimate()
|
||||||
|
.into(onei)
|
||||||
updateSeekBar()
|
updateSeekBar()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -338,7 +346,7 @@ class ViewMangaActivity : Activity() {
|
|||||||
//Glide.with(this@ViewMangaActivity).load(it).placeholder(R.drawable.bg_comment).into(holder.itemView.onei)
|
//Glide.with(this@ViewMangaActivity).load(it).placeholder(R.drawable.bg_comment).into(holder.itemView.onei)
|
||||||
holder.itemView.onei.setImageBitmap(it)
|
holder.itemView.onei.setImageBitmap(it)
|
||||||
}
|
}
|
||||||
else Glide.with(this@ViewMangaActivity).load(imgUrls[pos]).placeholder(R.drawable.bg_comment).timeout(10000).into(holder.itemView.onei)
|
else Glide.with(this@ViewMangaActivity).load(imgUrls[pos]).placeholder(R.drawable.ic_dl).dontAnimate().timeout(10000).into(holder.itemView.onei)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
override fun getItemCount(): Int {
|
||||||
@@ -377,7 +385,7 @@ class ViewMangaActivity : Activity() {
|
|||||||
class MyHandler(
|
class MyHandler(
|
||||||
private val infcard: View,
|
private val infcard: View,
|
||||||
private val toolsBox: ToolsBox
|
private val toolsBox: ToolsBox
|
||||||
) : Handler() {
|
) : Handler(Looper.myLooper()!!) {
|
||||||
private var infcShowed = false
|
private var infcShowed = false
|
||||||
private var delta = -1f
|
private var delta = -1f
|
||||||
get() {
|
get() {
|
||||||
@@ -429,7 +437,8 @@ class ViewMangaActivity : Activity() {
|
|||||||
var nextChapterUrl: String? = null
|
var nextChapterUrl: String? = null
|
||||||
var previousChapterUrl: String? = null
|
var previousChapterUrl: String? = null
|
||||||
var zipPosition = 0
|
var zipPosition = 0
|
||||||
var zipList: Array<out String>? = null
|
var zipList: Array<String>? = null
|
||||||
var cd: File? = null
|
var cd: File? = null
|
||||||
|
var pn = -1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -48,7 +48,7 @@ class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) {
|
|||||||
d?.pdwn?.progress = 0
|
d?.pdwn?.progress = 0
|
||||||
val selectDownloaded = d?.multiSelect?:false
|
val selectDownloaded = d?.multiSelect?:false
|
||||||
if (d?.haveSElectAll == true) {
|
if (d?.haveSElectAll == true) {
|
||||||
d?.tbtnlist?.listIterator()?.forEach { i ->
|
d?.tbtnlist?.forEach { i ->
|
||||||
if(i.freezesText) i.setBackgroundResource(R.drawable.rndbg_checked) else i.setBackgroundResource(R.drawable.toggle_button)
|
if(i.freezesText) i.setBackgroundResource(R.drawable.rndbg_checked) else i.setBackgroundResource(R.drawable.toggle_button)
|
||||||
i.isChecked = false
|
i.isChecked = false
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) {
|
|||||||
i.isChecked = true
|
i.isChecked = true
|
||||||
it.checkedChapter++
|
it.checkedChapter++
|
||||||
}
|
}
|
||||||
for (i in it.tbtnlist.listIterator()) {
|
for (i in it.tbtnlist) {
|
||||||
if(selectDownloaded) checkBtn(i, it)
|
if(selectDownloaded) checkBtn(i, it)
|
||||||
else if(!i.freezesText) checkBtn(i, it)
|
else if(!i.freezesText) checkBtn(i, it)
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ class DlHandler(activity: DlActivity, looper: Looper) : Handler(looper) {
|
|||||||
}
|
}
|
||||||
private fun setSize(pageNow: Int, tbtnNo: Int){
|
private fun setSize(pageNow: Int, tbtnNo: Int){
|
||||||
if(refreshSize || size == 0) {
|
if(refreshSize || size == 0) {
|
||||||
size = d?.tbtnUrlList?.get(tbtnNo)?.let { wmdlt?.get()?.getImgsCountByHash(it.substringAfterLast("/")) }?:0
|
size = d?.tbtnlist?.get(tbtnNo)?.hash?.let { wmdlt?.get()?.getImgsCountByHash(it) }?:0
|
||||||
refreshSize = false
|
refreshSize = false
|
||||||
}else if(pageNow == size) refreshSize = true
|
}else if(pageNow == size) refreshSize = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ class MainHandler(looper: Looper):Handler(looper) {
|
|||||||
}
|
}
|
||||||
private fun loadUrlInHiddenWebView(url: String){wm?.get()?.wh?.loadUrl(url)}
|
private fun loadUrlInHiddenWebView(url: String){wm?.get()?.wh?.loadUrl(url)}
|
||||||
private fun callViewManga(content: String){
|
private fun callViewManga(content: String){
|
||||||
val listChapter = content.split("\n")
|
val listChapter = content.split('\n')
|
||||||
if(!saveUrlsOnly) {
|
if(!saveUrlsOnly) {
|
||||||
ViewMangaActivity.titleText = listChapter[0].substringBeforeLast(" ")
|
ViewMangaActivity.titleText = listChapter[0].substringBeforeLast(' ')
|
||||||
ViewMangaActivity.nextChapterUrl = listChapter[1].let { if(it == "null") null else it }
|
ViewMangaActivity.nextChapterUrl = listChapter[1].let { if(it == "null") null else it }
|
||||||
ViewMangaActivity.previousChapterUrl = listChapter[2].let { if(it == "null") null else it }
|
ViewMangaActivity.previousChapterUrl = listChapter[2].let { if(it == "null") null else it }
|
||||||
ViewMangaActivity.imgUrls = arrayOf()
|
ViewMangaActivity.imgUrls = arrayOf()
|
||||||
@@ -39,7 +39,7 @@ class MainHandler(looper: Looper):Handler(looper) {
|
|||||||
} else{
|
} else{
|
||||||
var imgs = arrayOf<String>()
|
var imgs = arrayOf<String>()
|
||||||
for(i in 3 until listChapter.size) imgs += listChapter[i]
|
for(i in 3 until listChapter.size) imgs += listChapter[i]
|
||||||
wmdlt?.get()?.setChapterImgs(listChapter[0].substringAfterLast(" "), imgs)
|
wmdlt?.get()?.setChapterImgs(listChapter[0].substringAfterLast(' '), imgs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private fun updateLoadProgress(progress: Int){
|
private fun updateLoadProgress(progress: Int){
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package top.fumiama.copymanga.tool
|
package top.fumiama.copymanga.tool
|
||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.util.Log
|
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import top.fumiama.copymanga.activity.MainActivity.Companion.wm
|
import top.fumiama.copymanga.activity.MainActivity.Companion.wm
|
||||||
@@ -21,9 +20,6 @@ class PagesManager(w: WeakReference<ViewMangaActivity>) {
|
|||||||
private fun judgeNext() = v?.pageNum?:0 < v?.count?:0
|
private fun judgeNext() = v?.pageNum?:0 < v?.count?:0
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
private fun toPage(goNext:Boolean){
|
private fun toPage(goNext:Boolean){
|
||||||
val chapterUrl = if(goNext) ViewMangaActivity.nextChapterUrl else ViewMangaActivity.previousChapterUrl
|
|
||||||
val newZipPosition = ViewMangaActivity.zipPosition + (if(goNext) 1 else -1)
|
|
||||||
val hint = if(goNext) "下" else "上"
|
|
||||||
if (v?.clicked == false) {
|
if (v?.clicked == false) {
|
||||||
if (if(goNext)judgeNext() else judgePrevious()) {
|
if (if(goNext)judgeNext() else judgePrevious()) {
|
||||||
if(goNext) {
|
if(goNext) {
|
||||||
@@ -33,33 +29,42 @@ class PagesManager(w: WeakReference<ViewMangaActivity>) {
|
|||||||
v.scrollBack()
|
v.scrollBack()
|
||||||
isEndL = false
|
isEndL = false
|
||||||
}
|
}
|
||||||
} else if (chapterUrl != null) {
|
} else {
|
||||||
|
val chapterUrl = if(goNext) ViewMangaActivity.nextChapterUrl else ViewMangaActivity.previousChapterUrl
|
||||||
|
if (chapterUrl != null) {
|
||||||
if (if(goNext)isEndR else isEndL) {
|
if (if(goNext)isEndR else isEndL) {
|
||||||
|
if(!goNext) ViewMangaActivity.pn = -2
|
||||||
wm?.get()?.w?.loadUrl("javascript:invoke.clickClass(\"comicControlBottomTopClick\",${if(goNext)1 else 0});")
|
wm?.get()?.w?.loadUrl("javascript:invoke.clickClass(\"comicControlBottomTopClick\",${if(goNext)1 else 0});")
|
||||||
v.tt.canDo = false
|
v.tt.canDo = false
|
||||||
v.finish()
|
v.finish()
|
||||||
} else doubleTapToast(hint, goNext)
|
} else doubleTapToast(goNext)
|
||||||
} else if(v.dlZip2View && newZipPosition >= 0 && newZipPosition < ViewMangaActivity.zipList?.size?:0){
|
} else {
|
||||||
|
val newZipPosition = ViewMangaActivity.zipPosition + (if(goNext) 1 else -1)
|
||||||
|
if(v.dlZip2View && newZipPosition >= 0 && newZipPosition < ViewMangaActivity.zipList?.size?:0){
|
||||||
if (if(goNext)isEndR else isEndL){
|
if (if(goNext)isEndR else isEndL){
|
||||||
|
if(!goNext) ViewMangaActivity.pn = -2
|
||||||
ViewMangaActivity.zipPosition = newZipPosition
|
ViewMangaActivity.zipPosition = newZipPosition
|
||||||
ViewMangaActivity.titleText = ViewMangaActivity.zipList?.get(newZipPosition) ?: "null"
|
ViewMangaActivity.titleText = ViewMangaActivity.zipList?.get(newZipPosition) ?: "null"
|
||||||
ViewMangaActivity.zipFile = File(ViewMangaActivity.cd, ViewMangaActivity.titleText)
|
ViewMangaActivity.zipFile = File(ViewMangaActivity.cd, ViewMangaActivity.titleText)
|
||||||
v.startActivity(Intent(v, ViewMangaActivity::class.java))
|
v.startActivity(Intent(v, ViewMangaActivity::class.java))
|
||||||
v.tt.canDo = false
|
v.tt.canDo = false
|
||||||
v.finish()
|
v.finish()
|
||||||
}else doubleTapToast(hint, goNext)
|
}else doubleTapToast(goNext)
|
||||||
}
|
}
|
||||||
else Toast.makeText(
|
else Toast.makeText(
|
||||||
v.applicationContext,
|
v.applicationContext,
|
||||||
"已经到头了~",
|
"已经到头了~",
|
||||||
Toast.LENGTH_SHORT
|
Toast.LENGTH_SHORT
|
||||||
).show()
|
).show()
|
||||||
|
}
|
||||||
|
}
|
||||||
} else v?.hideObjs()
|
} else v?.hideObjs()
|
||||||
}
|
}
|
||||||
fun manageInfo(){
|
fun manageInfo(){
|
||||||
if (v?.clicked == false) v.showObjs() else v?.hideObjs()
|
if (v?.clicked == false) v.showObjs() else v?.hideObjs()
|
||||||
}
|
}
|
||||||
private fun doubleTapToast(hint: String, goNext: Boolean){
|
private fun doubleTapToast(goNext: Boolean){
|
||||||
|
val hint = if(goNext) "下" else "上"
|
||||||
Toast.makeText(
|
Toast.makeText(
|
||||||
v?.applicationContext,
|
v?.applicationContext,
|
||||||
"再次按下加载${hint}一章",
|
"再次按下加载${hint}一章",
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package top.fumiama.copymanga.view
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.util.AttributeSet
|
||||||
|
import android.widget.ToggleButton
|
||||||
|
|
||||||
|
class ChapterToggleButton: ToggleButton {
|
||||||
|
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int): super(context, attrs, defStyleAttr)
|
||||||
|
constructor(context: Context?, attrs: AttributeSet?): super(context, attrs)
|
||||||
|
constructor(context: Context?): super(context, null)
|
||||||
|
|
||||||
|
var url: CharSequence? = null
|
||||||
|
val hash get() = url?.toString()?.substringAfterLast('/')
|
||||||
|
var caption: CharSequence? = null
|
||||||
|
var index: Int = 0
|
||||||
|
var chapterName: CharSequence = "null"
|
||||||
|
set(value) {
|
||||||
|
textOn = value
|
||||||
|
textOff = value
|
||||||
|
text = value
|
||||||
|
field = value
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -117,34 +117,44 @@ class ScaleImageView : ImageView {
|
|||||||
* @return 如果传了matrix参数则将matrix填充后返回,否则new一个填充返回
|
* @return 如果传了matrix参数则将matrix填充后返回,否则new一个填充返回
|
||||||
*/
|
*/
|
||||||
private fun getInnerMatrix(matrix: Matrix?): Matrix {
|
private fun getInnerMatrix(matrix: Matrix?): Matrix {
|
||||||
var matrix = matrix
|
val m = matrix?:Matrix().let {
|
||||||
if (matrix == null) {
|
it.reset()
|
||||||
matrix = Matrix()
|
it
|
||||||
} else {
|
|
||||||
matrix.reset()
|
|
||||||
}
|
}
|
||||||
if (isReady) {
|
if (isReady) {
|
||||||
|
val imgX = drawable.intrinsicWidth.toFloat()
|
||||||
|
val imgY = drawable.intrinsicHeight.toFloat()
|
||||||
//原图大小
|
//原图大小
|
||||||
val tempSrc = MathUtils.rectFTake(
|
val tempSrc = rectFTake(0f, 0f, imgX, imgY)
|
||||||
0f,
|
//layoutParams.height = (imgY / imgX * width + 0.5).toInt()
|
||||||
0f,
|
//invalidate()
|
||||||
drawable.intrinsicWidth.toFloat(),
|
|
||||||
drawable.intrinsicHeight.toFloat()
|
|
||||||
)
|
|
||||||
//控件大小
|
//控件大小
|
||||||
val tempDst = MathUtils.rectFTake(
|
val tempDst = rectFTake(0f, 0f, width.toFloat(), height.toFloat())
|
||||||
0f,
|
//计算fit center矩阵
|
||||||
0f,
|
m.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
|
||||||
width.toFloat(),
|
//释放临时对象
|
||||||
height.toFloat()
|
rectFGiven(tempDst)
|
||||||
)
|
rectFGiven(tempSrc)
|
||||||
|
}
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
fun setHeight2FitImgWidth(){
|
||||||
|
matrix.reset()
|
||||||
|
val imgX = drawable.intrinsicWidth.toFloat()
|
||||||
|
val imgY = drawable.intrinsicHeight.toFloat()
|
||||||
|
//Log.d("MySIV", "ix: $imgX, iy: $imgY, w: $width, h: $height")
|
||||||
|
//原图大小
|
||||||
|
val tempSrc = rectFTake(0f, 0f, imgX, imgY)
|
||||||
|
layoutParams.height = (imgY / imgX * width + 0.5).toInt()
|
||||||
|
invalidate()
|
||||||
|
//控件大小
|
||||||
|
val tempDst = rectFTake(0f, 0f, width.toFloat(), height.toFloat())
|
||||||
//计算fit center矩阵
|
//计算fit center矩阵
|
||||||
matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
|
matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
|
||||||
//释放临时对象
|
//释放临时对象
|
||||||
MathUtils.rectFGiven(tempDst)
|
rectFGiven(tempDst)
|
||||||
MathUtils.rectFGiven(tempSrc)
|
rectFGiven(tempSrc)
|
||||||
}
|
|
||||||
return matrix
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -161,11 +171,10 @@ class ScaleImageView : ImageView {
|
|||||||
*/
|
*/
|
||||||
private fun getCurrentImageMatrix(matrix: Matrix): Matrix {
|
private fun getCurrentImageMatrix(matrix: Matrix): Matrix {
|
||||||
//获取内部变换矩阵
|
//获取内部变换矩阵
|
||||||
var matrix = matrix
|
val m = getInnerMatrix(matrix)
|
||||||
matrix = getInnerMatrix(matrix)
|
|
||||||
//乘上外部变换矩阵
|
//乘上外部变换矩阵
|
||||||
matrix.postConcat(mOuterMatrix)
|
m.postConcat(mOuterMatrix)
|
||||||
return matrix
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -179,26 +188,20 @@ class ScaleImageView : ImageView {
|
|||||||
* @see .getCurrentImageMatrix
|
* @see .getCurrentImageMatrix
|
||||||
*/
|
*/
|
||||||
private fun getImageBound(rectF: RectF?): RectF {
|
private fun getImageBound(rectF: RectF?): RectF {
|
||||||
var rectF = rectF
|
var rf = rectF
|
||||||
if (rectF == null) {
|
if (rf == null) rf = RectF() else rf.setEmpty()
|
||||||
rectF = RectF()
|
if (isReady) {
|
||||||
} else {
|
|
||||||
rectF.setEmpty()
|
|
||||||
}
|
|
||||||
return if (!isReady) {
|
|
||||||
rectF
|
|
||||||
} else {
|
|
||||||
//申请一个空matrix
|
//申请一个空matrix
|
||||||
val matrix = MathUtils.matrixTake()
|
val matrix = matrixTake()
|
||||||
//获取当前总变换矩阵
|
//获取当前总变换矩阵
|
||||||
getCurrentImageMatrix(matrix)
|
getCurrentImageMatrix(matrix)
|
||||||
//对原图矩形进行变换得到当前显示矩形
|
//对原图矩形进行变换得到当前显示矩形
|
||||||
rectF[0f, 0f, drawable.intrinsicWidth.toFloat()] = drawable.intrinsicHeight.toFloat()
|
rf[0f, 0f, drawable.intrinsicWidth.toFloat()] = drawable.intrinsicHeight.toFloat()
|
||||||
matrix.mapRect(rectF)
|
matrix.mapRect(rf)
|
||||||
//释放临时matrix
|
//释放临时matrix
|
||||||
MathUtils.matrixGiven(matrix)
|
matrixGiven(matrix)
|
||||||
rectF
|
|
||||||
}
|
}
|
||||||
|
return rf
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -508,11 +511,9 @@ class ScaleImageView : ImageView {
|
|||||||
outerScale: Float
|
outerScale: Float
|
||||||
): Float {
|
): Float {
|
||||||
val currentScale = innerScale * outerScale
|
val currentScale = innerScale * outerScale
|
||||||
return if (currentScale < maxScale) {
|
Log.d("MySIV", "current scale: $currentScale, max scale: $maxScale")
|
||||||
maxScale
|
return if (currentScale < maxScale * 0.9f) maxScale
|
||||||
} else {
|
else innerScale
|
||||||
innerScale
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////初始化////////////////////////////////
|
////////////////////////////////初始化////////////////////////////////
|
||||||
@@ -520,10 +521,7 @@ class ScaleImageView : ImageView {
|
|||||||
initView()
|
initView()
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?) : super(
|
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
|
||||||
context,
|
|
||||||
attrs
|
|
||||||
) {
|
|
||||||
initView()
|
initView()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,9 +546,9 @@ class ScaleImageView : ImageView {
|
|||||||
try {
|
try {
|
||||||
//在绘制前设置变换矩阵
|
//在绘制前设置变换矩阵
|
||||||
if (isReady) {
|
if (isReady) {
|
||||||
val matrix = MathUtils.matrixTake()
|
val matrix = matrixTake()
|
||||||
imageMatrix = getCurrentImageMatrix(matrix)
|
imageMatrix = getCurrentImageMatrix(matrix)
|
||||||
MathUtils.matrixGiven(matrix)
|
matrixGiven(matrix)
|
||||||
}
|
}
|
||||||
//对图像做遮罩处理
|
//对图像做遮罩处理
|
||||||
if (mMask != null) {
|
if (mMask != null) {
|
||||||
@@ -563,7 +561,7 @@ class ScaleImageView : ImageView {
|
|||||||
}
|
}
|
||||||
}catch (e:Exception){
|
}catch (e:Exception){
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
ViewMangaActivity.va?.get()?.toolsBox?.toastError("图片加载错误", false)
|
ViewMangaActivity.va?.get()?.toolsBox?.toastError("图片加载错误,请尝试下载后使用较低图片质量查看", false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
////////////////////////////////有效性判断////////////////////////////////
|
////////////////////////////////有效性判断////////////////////////////////
|
||||||
@@ -576,75 +574,6 @@ class ScaleImageView : ImageView {
|
|||||||
*/
|
*/
|
||||||
private val isReady: Boolean
|
private val isReady: Boolean
|
||||||
get() = drawable != null && drawable.intrinsicWidth > 0 && drawable.intrinsicHeight > 0 && width > 0 && height > 0
|
get() = drawable != null && drawable.intrinsicWidth > 0 && drawable.intrinsicHeight > 0 && width > 0 && height > 0
|
||||||
////////////////////////////////mask动画处理////////////////////////////////
|
|
||||||
/**
|
|
||||||
* mask修改的动画
|
|
||||||
*
|
|
||||||
* 和图片的动画相互独立.
|
|
||||||
*
|
|
||||||
@see .zoomMaskTo
|
|
||||||
*/
|
|
||||||
//private var mMaskAnimator: MaskAnimator? = null
|
|
||||||
|
|
||||||
/**
|
|
||||||
* mask变换动画
|
|
||||||
*
|
|
||||||
* 将mask从一个rect动画到另外一个rect
|
|
||||||
|
|
||||||
private inner class MaskAnimator(start: RectF, end: RectF, duration: Long) :
|
|
||||||
ValueAnimator(), AnimatorUpdateListener {
|
|
||||||
/**
|
|
||||||
* 开始mask
|
|
||||||
*/
|
|
||||||
private val mStart = FloatArray(4)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 结束mask
|
|
||||||
*/
|
|
||||||
private val mEnd = FloatArray(4)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 中间结果mask
|
|
||||||
*/
|
|
||||||
private val mResult = FloatArray(4)
|
|
||||||
override fun onAnimationUpdate(animation: ValueAnimator) {
|
|
||||||
//获取动画进度,0-1范围
|
|
||||||
val value = animation.animatedValue as Float
|
|
||||||
//根据进度对起点终点之间做插值
|
|
||||||
for (i in 0..3) {
|
|
||||||
mResult[i] = mStart[i] + (mEnd[i] - mStart[i]) * value
|
|
||||||
}
|
|
||||||
//期间mask有可能被置空了,所以判断一下
|
|
||||||
if (mMask == null) {
|
|
||||||
mMask = RectF()
|
|
||||||
}
|
|
||||||
//设置新的mask并绘制
|
|
||||||
mMask!![mResult[0], mResult[1], mResult[2]] = mResult[3]
|
|
||||||
invalidate()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建mask变换动画
|
|
||||||
*
|
|
||||||
@param start 动画起始状态
|
|
||||||
@param end 动画终点状态
|
|
||||||
@param duration 动画持续时间
|
|
||||||
*/
|
|
||||||
init {
|
|
||||||
setFloatValues(0f, 1f)
|
|
||||||
setDuration(duration)
|
|
||||||
addUpdateListener(this)
|
|
||||||
//将起点终点拷贝到数组方便计算
|
|
||||||
mStart[0] = start.left
|
|
||||||
mStart[1] = start.top
|
|
||||||
mStart[2] = start.right
|
|
||||||
mStart[3] = start.bottom
|
|
||||||
mEnd[0] = end.left
|
|
||||||
mEnd[1] = end.top
|
|
||||||
mEnd[2] = end.right
|
|
||||||
mEnd[3] = end.bottom
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
////////////////////////////////手势动画处理////////////////////////////////
|
////////////////////////////////手势动画处理////////////////////////////////
|
||||||
/**
|
/**
|
||||||
* 在单指模式下:
|
* 在单指模式下:
|
||||||
@@ -766,14 +695,14 @@ class ScaleImageView : ImageView {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
private val isBig: Boolean
|
private val isBig: Boolean
|
||||||
get() = MathUtils.getMatrixScale(mOuterMatrix)[0] > 1f
|
get() = getMatrixScale(mOuterMatrix)[0] > 1f
|
||||||
|
|
||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
@SuppressLint("ClickableViewAccessibility")
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
override fun onTouchEvent(event: MotionEvent): Boolean {
|
override fun onTouchEvent(event: MotionEvent): Boolean {
|
||||||
super.onTouchEvent(event)
|
super.onTouchEvent(event)
|
||||||
val action = event.action and MotionEvent.ACTION_MASK
|
val action = event.action and MotionEvent.ACTION_MASK
|
||||||
Log.d("MySi", "Outer Scale: ${MathUtils.getMatrixScale(mOuterMatrix)[0]}")
|
Log.d("MySi", "Outer Scale: ${getMatrixScale(mOuterMatrix)[0]}")
|
||||||
//最后一个点抬起或者取消,结束所有模式
|
//最后一个点抬起或者取消,结束所有模式
|
||||||
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
||||||
//如果之前是缩放模式,还需要触发一下缩放结束动画
|
//如果之前是缩放模式,还需要触发一下缩放结束动画
|
||||||
@@ -829,14 +758,14 @@ class ScaleImageView : ImageView {
|
|||||||
//在缩放模式下移动
|
//在缩放模式下移动
|
||||||
} else if (pinchMode == PINCH_MODE_SCALE && event.pointerCount > 1) {
|
} else if (pinchMode == PINCH_MODE_SCALE && event.pointerCount > 1) {
|
||||||
//两个缩放点间的距离
|
//两个缩放点间的距离
|
||||||
val distance = MathUtils.getDistance(
|
val distance = getDistance(
|
||||||
event.getX(0),
|
event.getX(0),
|
||||||
event.getY(0),
|
event.getY(0),
|
||||||
event.getX(1),
|
event.getX(1),
|
||||||
event.getY(1)
|
event.getY(1)
|
||||||
)
|
)
|
||||||
//保存缩放点中点
|
//保存缩放点中点
|
||||||
val lineCenter = MathUtils.getCenterPoint(
|
val lineCenter = getCenterPoint(
|
||||||
event.getX(0),
|
event.getX(0),
|
||||||
event.getY(0),
|
event.getY(0),
|
||||||
event.getX(1),
|
event.getX(1),
|
||||||
@@ -869,7 +798,7 @@ class ScaleImageView : ImageView {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
//原图方框
|
//原图方框
|
||||||
val bound = MathUtils.rectFTake()
|
val bound = rectFTake()
|
||||||
getImageBound(bound)
|
getImageBound(bound)
|
||||||
//控件大小
|
//控件大小
|
||||||
val displayWidth = width.toFloat()
|
val displayWidth = width.toFloat()
|
||||||
@@ -927,7 +856,7 @@ class ScaleImageView : ImageView {
|
|||||||
//触发重绘
|
//触发重绘
|
||||||
//检查是否有变化
|
//检查是否有变化
|
||||||
}
|
}
|
||||||
MathUtils.rectFGiven(bound)
|
rectFGiven(bound)
|
||||||
//应用移动变换
|
//应用移动变换
|
||||||
mOuterMatrix.postTranslate(xDiff, yDiff)
|
mOuterMatrix.postTranslate(xDiff, yDiff)
|
||||||
dispatchOuterMatrixChanged()
|
dispatchOuterMatrixChanged()
|
||||||
@@ -959,13 +888,13 @@ class ScaleImageView : ImageView {
|
|||||||
//但是有可能外部设定了不规范的值.
|
//但是有可能外部设定了不规范的值.
|
||||||
//但是后续的scale操作会将xy不等的缩放值纠正,改成和x方向相同
|
//但是后续的scale操作会将xy不等的缩放值纠正,改成和x方向相同
|
||||||
mScaleBase =
|
mScaleBase =
|
||||||
MathUtils.getMatrixScale(mOuterMatrix)[0] / MathUtils.getDistance(x1, y1, x2, y2)
|
getMatrixScale(mOuterMatrix)[0] / getDistance(x1, y1, x2, y2)
|
||||||
//两手指的中点在屏幕上落在了图片的某个点上,图片上的这个点在经过总矩阵变换后和手指中点相同
|
//两手指的中点在屏幕上落在了图片的某个点上,图片上的这个点在经过总矩阵变换后和手指中点相同
|
||||||
//现在我们需要得到图片上这个点在图片是fit center状态下在屏幕上的位置
|
//现在我们需要得到图片上这个点在图片是fit center状态下在屏幕上的位置
|
||||||
//因为后续的计算都是基于图片是fit center状态下进行变换
|
//因为后续的计算都是基于图片是fit center状态下进行变换
|
||||||
//所以需要把两手指中点除以外层变换矩阵得到mScaleCenter
|
//所以需要把两手指中点除以外层变换矩阵得到mScaleCenter
|
||||||
val center = MathUtils.inverseMatrixPoint(
|
val center = inverseMatrixPoint(
|
||||||
MathUtils.getCenterPoint(
|
getCenterPoint(
|
||||||
x1,
|
x1,
|
||||||
y1,
|
y1,
|
||||||
x2,
|
x2,
|
||||||
@@ -998,14 +927,14 @@ class ScaleImageView : ImageView {
|
|||||||
}
|
}
|
||||||
//计算图片从fit center状态到目标状态的缩放比例
|
//计算图片从fit center状态到目标状态的缩放比例
|
||||||
val scale = scaleBase * distance
|
val scale = scaleBase * distance
|
||||||
val matrix = MathUtils.matrixTake()
|
val matrix = matrixTake()
|
||||||
//按照图片缩放中心缩放,并且让缩放中心在缩放点中点上
|
//按照图片缩放中心缩放,并且让缩放中心在缩放点中点上
|
||||||
matrix.postScale(scale, scale, scaleCenter.x, scaleCenter.y)
|
matrix.postScale(scale, scale, scaleCenter.x, scaleCenter.y)
|
||||||
//让图片的缩放中点跟随手指缩放中点
|
//让图片的缩放中点跟随手指缩放中点
|
||||||
matrix.postTranslate(lineCenter.x - scaleCenter.x, lineCenter.y - scaleCenter.y)
|
matrix.postTranslate(lineCenter.x - scaleCenter.x, lineCenter.y - scaleCenter.y)
|
||||||
//应用变换
|
//应用变换
|
||||||
mOuterMatrix.set(matrix)
|
mOuterMatrix.set(matrix)
|
||||||
MathUtils.matrixGiven(matrix)
|
matrixGiven(matrix)
|
||||||
dispatchOuterMatrixChanged()
|
dispatchOuterMatrixChanged()
|
||||||
//重绘
|
//重绘
|
||||||
invalidate()
|
invalidate()
|
||||||
@@ -1029,11 +958,11 @@ class ScaleImageView : ImageView {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
//获取第一层变换矩阵
|
//获取第一层变换矩阵
|
||||||
val innerMatrix = MathUtils.matrixTake()
|
val innerMatrix = matrixTake()
|
||||||
getInnerMatrix(innerMatrix)
|
getInnerMatrix(innerMatrix)
|
||||||
//当前总的缩放比例
|
//当前总的缩放比例
|
||||||
val innerScale = MathUtils.getMatrixScale(innerMatrix)[0]
|
val innerScale = getMatrixScale(innerMatrix)[0]
|
||||||
val outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0]
|
val outerScale = getMatrixScale(mOuterMatrix)[0]
|
||||||
val currentScale = innerScale * outerScale
|
val currentScale = innerScale * outerScale
|
||||||
//控件大小
|
//控件大小
|
||||||
val displayWidth = width.toFloat()
|
val displayWidth = width.toFloat()
|
||||||
@@ -1043,6 +972,7 @@ class ScaleImageView : ImageView {
|
|||||||
//接下来要放大的大小
|
//接下来要放大的大小
|
||||||
var nextScale = calculateNextScale(innerScale, outerScale)
|
var nextScale = calculateNextScale(innerScale, outerScale)
|
||||||
//如果接下来放大大于最大值或者小于fit center值,则取边界
|
//如果接下来放大大于最大值或者小于fit center值,则取边界
|
||||||
|
Log.d("MySIV", "Next scale: $nextScale, Max scale: $maxScale, Inner scale: $innerScale")
|
||||||
if (nextScale > maxScale) {
|
if (nextScale > maxScale) {
|
||||||
nextScale = maxScale
|
nextScale = maxScale
|
||||||
}
|
}
|
||||||
@@ -1050,15 +980,15 @@ class ScaleImageView : ImageView {
|
|||||||
nextScale = innerScale
|
nextScale = innerScale
|
||||||
}
|
}
|
||||||
//开始计算缩放动画的结果矩阵
|
//开始计算缩放动画的结果矩阵
|
||||||
val animEnd = MathUtils.matrixTake(mOuterMatrix)
|
val animEnd = matrixTake(mOuterMatrix)
|
||||||
//计算还需缩放的倍数
|
//计算还需缩放的倍数
|
||||||
animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y)
|
animEnd.postScale(nextScale / currentScale, nextScale / currentScale, x, y)
|
||||||
//将放大点移动到控件中心
|
//将放大点移动到控件中心
|
||||||
animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y)
|
animEnd.postTranslate(displayWidth / 2f - x, displayHeight / 2f - y)
|
||||||
//得到放大之后的图片方框
|
//得到放大之后的图片方框
|
||||||
val testMatrix = MathUtils.matrixTake(innerMatrix)
|
val testMatrix = matrixTake(innerMatrix)
|
||||||
testMatrix.postConcat(animEnd)
|
testMatrix.postConcat(animEnd)
|
||||||
val testBound = MathUtils.rectFTake(
|
val testBound = rectFTake(
|
||||||
0f,
|
0f,
|
||||||
0f,
|
0f,
|
||||||
drawable.intrinsicWidth.toFloat(),
|
drawable.intrinsicWidth.toFloat(),
|
||||||
@@ -1106,10 +1036,10 @@ class ScaleImageView : ImageView {
|
|||||||
mScaleAnimator = ScaleAnimator(mOuterMatrix, animEnd)
|
mScaleAnimator = ScaleAnimator(mOuterMatrix, animEnd)
|
||||||
mScaleAnimator!!.start()
|
mScaleAnimator!!.start()
|
||||||
//清理临时变量
|
//清理临时变量
|
||||||
MathUtils.rectFGiven(testBound)
|
rectFGiven(testBound)
|
||||||
MathUtils.matrixGiven(testMatrix)
|
matrixGiven(testMatrix)
|
||||||
MathUtils.matrixGiven(animEnd)
|
matrixGiven(animEnd)
|
||||||
MathUtils.matrixGiven(innerMatrix)
|
matrixGiven(innerMatrix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1125,13 +1055,13 @@ class ScaleImageView : ImageView {
|
|||||||
//是否修正了位置
|
//是否修正了位置
|
||||||
var change = false
|
var change = false
|
||||||
//获取图片整体的变换矩阵
|
//获取图片整体的变换矩阵
|
||||||
val currentMatrix = MathUtils.matrixTake()
|
val currentMatrix = matrixTake()
|
||||||
getCurrentImageMatrix(currentMatrix)
|
getCurrentImageMatrix(currentMatrix)
|
||||||
//整体缩放比例
|
//整体缩放比例
|
||||||
val currentScale =
|
val currentScale =
|
||||||
MathUtils.getMatrixScale(currentMatrix)[0]
|
getMatrixScale(currentMatrix)[0]
|
||||||
//第二层缩放比例
|
//第二层缩放比例
|
||||||
val outerScale = MathUtils.getMatrixScale(mOuterMatrix)[0]
|
val outerScale = getMatrixScale(mOuterMatrix)[0]
|
||||||
//控件大小
|
//控件大小
|
||||||
val displayWidth = width.toFloat()
|
val displayWidth = width.toFloat()
|
||||||
val displayHeight = height.toFloat()
|
val displayHeight = height.toFloat()
|
||||||
@@ -1155,9 +1085,9 @@ class ScaleImageView : ImageView {
|
|||||||
change = true
|
change = true
|
||||||
}
|
}
|
||||||
//尝试根据缩放点进行缩放修正
|
//尝试根据缩放点进行缩放修正
|
||||||
val testMatrix = MathUtils.matrixTake(currentMatrix)
|
val testMatrix = matrixTake(currentMatrix)
|
||||||
testMatrix.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y)
|
testMatrix.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y)
|
||||||
val testBound = MathUtils.rectFTake(
|
val testBound = rectFTake(
|
||||||
0f,
|
0f,
|
||||||
0f,
|
0f,
|
||||||
drawable.intrinsicWidth.toFloat(),
|
drawable.intrinsicWidth.toFloat(),
|
||||||
@@ -1215,7 +1145,7 @@ class ScaleImageView : ImageView {
|
|||||||
//只有有执行修正才执行动画
|
//只有有执行修正才执行动画
|
||||||
if (change) {
|
if (change) {
|
||||||
//计算结束矩阵
|
//计算结束矩阵
|
||||||
val animEnd = MathUtils.matrixTake(mOuterMatrix)
|
val animEnd = matrixTake(mOuterMatrix)
|
||||||
animEnd.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y)
|
animEnd.postScale(scalePost, scalePost, mLastMovePoint.x, mLastMovePoint.y)
|
||||||
animEnd.postTranslate(postX, postY)
|
animEnd.postTranslate(postX, postY)
|
||||||
//清理当前可能正在执行的动画
|
//清理当前可能正在执行的动画
|
||||||
@@ -1224,12 +1154,12 @@ class ScaleImageView : ImageView {
|
|||||||
mScaleAnimator = ScaleAnimator(mOuterMatrix, animEnd)
|
mScaleAnimator = ScaleAnimator(mOuterMatrix, animEnd)
|
||||||
mScaleAnimator!!.start()
|
mScaleAnimator!!.start()
|
||||||
//清理临时变量
|
//清理临时变量
|
||||||
MathUtils.matrixGiven(animEnd)
|
matrixGiven(animEnd)
|
||||||
}
|
}
|
||||||
//清理临时变量
|
//清理临时变量
|
||||||
MathUtils.rectFGiven(testBound)
|
rectFGiven(testBound)
|
||||||
MathUtils.matrixGiven(testMatrix)
|
matrixGiven(testMatrix)
|
||||||
MathUtils.matrixGiven(currentMatrix)
|
matrixGiven(currentMatrix)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1288,7 +1218,7 @@ class ScaleImageView : ImageView {
|
|||||||
mVector[0] *= FLING_DAMPING_FACTOR
|
mVector[0] *= FLING_DAMPING_FACTOR
|
||||||
mVector[1] *= FLING_DAMPING_FACTOR
|
mVector[1] *= FLING_DAMPING_FACTOR
|
||||||
//速度太小或者不能移动了就结束
|
//速度太小或者不能移动了就结束
|
||||||
if (!result || MathUtils.getDistance(
|
if (!result || getDistance(
|
||||||
0f,
|
0f,
|
||||||
0f,
|
0f,
|
||||||
mVector[0],
|
mVector[0],
|
||||||
@@ -1496,7 +1426,7 @@ class ScaleImageView : ImageView {
|
|||||||
/**
|
/**
|
||||||
* 数学计算工具类
|
* 数学计算工具类
|
||||||
*/
|
*/
|
||||||
object MathUtils {
|
companion object {
|
||||||
/**
|
/**
|
||||||
* 矩阵对象池
|
* 矩阵对象池
|
||||||
*/
|
*/
|
||||||
@@ -1505,9 +1435,7 @@ class ScaleImageView : ImageView {
|
|||||||
/**
|
/**
|
||||||
* 获取矩阵对象
|
* 获取矩阵对象
|
||||||
*/
|
*/
|
||||||
fun matrixTake(): Matrix {
|
fun matrixTake() = mMatrixPool.take()!!
|
||||||
return mMatrixPool.take()!!
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取某个矩阵的copy
|
* 获取某个矩阵的copy
|
||||||
@@ -1653,192 +1581,6 @@ class ScaleImageView : ImageView {
|
|||||||
FloatArray(2)
|
FloatArray(2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算两个矩形之间的变换矩阵
|
|
||||||
*
|
|
||||||
* unknownMatrix.mapRect(to, from)
|
|
||||||
* 已知from矩形和to矩形,求unknownMatrix
|
|
||||||
*
|
|
||||||
@param from
|
|
||||||
@param to
|
|
||||||
@param result unknownMatrix
|
|
||||||
|
|
||||||
fun calculateRectTranslateMatrix(
|
|
||||||
from: RectF?,
|
|
||||||
to: RectF?,
|
|
||||||
result: Matrix?
|
|
||||||
) {
|
|
||||||
if (from == null || to == null || result == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (from.width() == 0f || from.height() == 0f) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
result.reset()
|
|
||||||
result.postTranslate(-from.left, -from.top)
|
|
||||||
result.postScale(to.width() / from.width(), to.height() / from.height())
|
|
||||||
result.postTranslate(to.left, to.top)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 计算图片在某个ImageView中的显示矩形
|
|
||||||
*
|
|
||||||
@param container ImageView的Rect
|
|
||||||
@param srcWidth 图片的宽度
|
|
||||||
@param srcHeight 图片的高度
|
|
||||||
@param scaleType 图片在ImageView中的ScaleType
|
|
||||||
@param result 图片应该在ImageView中展示的矩形
|
|
||||||
|
|
||||||
fun calculateScaledRectInContainer(
|
|
||||||
container: RectF?,
|
|
||||||
srcWidth: Float,
|
|
||||||
srcHeight: Float,
|
|
||||||
scaleType: ScaleType?,
|
|
||||||
result: RectF?
|
|
||||||
) {
|
|
||||||
var scaleType = scaleType
|
|
||||||
if (container == null || result == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (srcWidth == 0f || srcHeight == 0f) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//默认scaleType为fit center
|
|
||||||
if (scaleType == null) {
|
|
||||||
scaleType = ScaleType.FIT_CENTER
|
|
||||||
}
|
|
||||||
result.setEmpty()
|
|
||||||
if (ScaleType.FIT_XY == scaleType) {
|
|
||||||
result.set(container)
|
|
||||||
} else if (ScaleType.CENTER == scaleType) {
|
|
||||||
val matrix = matrixTake()
|
|
||||||
val rect = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
matrix.setTranslate(
|
|
||||||
(container.width() - srcWidth) * 0.5f,
|
|
||||||
(container.height() - srcHeight) * 0.5f
|
|
||||||
)
|
|
||||||
matrix.mapRect(result, rect)
|
|
||||||
rectFGiven(rect)
|
|
||||||
matrixGiven(matrix)
|
|
||||||
result.left += container.left
|
|
||||||
result.right += container.left
|
|
||||||
result.top += container.top
|
|
||||||
result.bottom += container.top
|
|
||||||
} else if (ScaleType.CENTER_CROP == scaleType) {
|
|
||||||
val matrix = matrixTake()
|
|
||||||
val rect = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val scale: Float
|
|
||||||
var dx = 0f
|
|
||||||
var dy = 0f
|
|
||||||
if (srcWidth * container.height() > container.width() * srcHeight) {
|
|
||||||
scale = container.height() / srcHeight
|
|
||||||
dx = (container.width() - srcWidth * scale) * 0.5f
|
|
||||||
} else {
|
|
||||||
scale = container.width() / srcWidth
|
|
||||||
dy = (container.height() - srcHeight * scale) * 0.5f
|
|
||||||
}
|
|
||||||
matrix.setScale(scale, scale)
|
|
||||||
matrix.postTranslate(dx, dy)
|
|
||||||
matrix.mapRect(result, rect)
|
|
||||||
rectFGiven(rect)
|
|
||||||
matrixGiven(matrix)
|
|
||||||
result.left += container.left
|
|
||||||
result.right += container.left
|
|
||||||
result.top += container.top
|
|
||||||
result.bottom += container.top
|
|
||||||
} else if (ScaleType.CENTER_INSIDE == scaleType) {
|
|
||||||
val matrix = matrixTake()
|
|
||||||
val rect = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val scale: Float
|
|
||||||
val dx: Float
|
|
||||||
val dy: Float
|
|
||||||
scale = if (srcWidth <= container.width() && srcHeight <= container.height()) {
|
|
||||||
1f
|
|
||||||
} else {
|
|
||||||
Math.min(
|
|
||||||
container.width() / srcWidth,
|
|
||||||
container.height() / srcHeight
|
|
||||||
)
|
|
||||||
}
|
|
||||||
dx = (container.width() - srcWidth * scale) * 0.5f
|
|
||||||
dy = (container.height() - srcHeight * scale) * 0.5f
|
|
||||||
matrix.setScale(scale, scale)
|
|
||||||
matrix.postTranslate(dx, dy)
|
|
||||||
matrix.mapRect(result, rect)
|
|
||||||
rectFGiven(rect)
|
|
||||||
matrixGiven(matrix)
|
|
||||||
result.left += container.left
|
|
||||||
result.right += container.left
|
|
||||||
result.top += container.top
|
|
||||||
result.bottom += container.top
|
|
||||||
} else if (ScaleType.FIT_CENTER == scaleType) {
|
|
||||||
val matrix = matrixTake()
|
|
||||||
val rect = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val tempSrc = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val tempDst = rectFTake(
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
container.width(),
|
|
||||||
container.height()
|
|
||||||
)
|
|
||||||
matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.CENTER)
|
|
||||||
matrix.mapRect(result, rect)
|
|
||||||
rectFGiven(tempDst)
|
|
||||||
rectFGiven(tempSrc)
|
|
||||||
rectFGiven(rect)
|
|
||||||
matrixGiven(matrix)
|
|
||||||
result.left += container.left
|
|
||||||
result.right += container.left
|
|
||||||
result.top += container.top
|
|
||||||
result.bottom += container.top
|
|
||||||
} else if (ScaleType.FIT_START == scaleType) {
|
|
||||||
val matrix = matrixTake()
|
|
||||||
val rect = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val tempSrc = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val tempDst = rectFTake(
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
container.width(),
|
|
||||||
container.height()
|
|
||||||
)
|
|
||||||
matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.START)
|
|
||||||
matrix.mapRect(result, rect)
|
|
||||||
rectFGiven(tempDst)
|
|
||||||
rectFGiven(tempSrc)
|
|
||||||
rectFGiven(rect)
|
|
||||||
matrixGiven(matrix)
|
|
||||||
result.left += container.left
|
|
||||||
result.right += container.left
|
|
||||||
result.top += container.top
|
|
||||||
result.bottom += container.top
|
|
||||||
} else if (ScaleType.FIT_END == scaleType) {
|
|
||||||
val matrix = matrixTake()
|
|
||||||
val rect = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val tempSrc = rectFTake(0f, 0f, srcWidth, srcHeight)
|
|
||||||
val tempDst = rectFTake(
|
|
||||||
0f,
|
|
||||||
0f,
|
|
||||||
container.width(),
|
|
||||||
container.height()
|
|
||||||
)
|
|
||||||
matrix.setRectToRect(tempSrc, tempDst, Matrix.ScaleToFit.END)
|
|
||||||
matrix.mapRect(result, rect)
|
|
||||||
rectFGiven(tempDst)
|
|
||||||
rectFGiven(tempSrc)
|
|
||||||
rectFGiven(rect)
|
|
||||||
matrixGiven(matrix)
|
|
||||||
result.left += container.left
|
|
||||||
result.right += container.left
|
|
||||||
result.top += container.top
|
|
||||||
result.bottom += container.top
|
|
||||||
} else {
|
|
||||||
result.set(container)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
////////////////////////////////配置参数////////////////////////////////
|
////////////////////////////////配置参数////////////////////////////////
|
||||||
/**
|
/**
|
||||||
* 图片缩放动画时间
|
* 图片缩放动画时间
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ToggleButton xmlns:android="http://schemas.android.com/apk/res/android"
|
<top.fumiama.copymanga.view.ChapterToggleButton xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:id="@+id/tbtn"
|
android:id="@+id/tbtn"
|
||||||
android:layout_width="64dp"
|
android:layout_width="64dp"
|
||||||
|
|||||||
Reference in New Issue
Block a user