Commit a4c385ca authored by wanglei's avatar wanglei

初始化

parent fa5cb099

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

package com.base.pdfoneread.bean
/**
* 全局数据数据
*/
import com.base.pdfoneread.bean.DocumentBean.Companion.TYPE_ALL
object GlobalDocumentData {
val GlobalPdfList = arrayListOf<DocumentBean>()
val GlobalWordList = arrayListOf<DocumentBean>()
var GlobalExcelList = arrayListOf<DocumentBean>()
var GlobalPptList = arrayListOf<DocumentBean>()
}
\ No newline at end of file
......@@ -4,7 +4,7 @@ import com.base.pdfoneread.R
data class HomeUIBean(
val key: String = KEY_ALL,
val key: String = "",
val icon: Int = R.mipmap.h_pdf_all,
val des: String = "All",
var uiType: Int = UI_TYPE_GRID,
......
......@@ -22,6 +22,7 @@ class DocumentActivity : BaseActivity<ActivityDocumentBinding>() {
override val binding: ActivityDocumentBinding by lazy {
ActivityDocumentBinding.inflate(layoutInflater)
}
private var adapter: DocumentAdapter? = null
override fun initView() {
......@@ -51,24 +52,62 @@ class DocumentActivity : BaseActivity<ActivityDocumentBinding>() {
binding.tvTittle.text = getString(R.string.ppt_files)
}
}
adapter = DocumentAdapter(this)
binding.rv.adapter = adapter
}
override fun initListener() {
super.initListener()
initPreData()
}
private fun initPreData() {
when (type) {
TYPE_ALL -> {
adapter?.submitList(getGlobalAllList())
}
TYPE_PDF -> {
adapter?.submitList(GlobalPdfList)
}
TYPE_WORD -> {
adapter?.submitList(GlobalWordList)
}
TYPE_EXCEL -> {
adapter?.submitList(GlobalExcelList)
}
TYPE_PPT -> {
adapter?.submitList(GlobalPptList)
}
}
initData()
}
private fun initData() = lifecycleScope.launch(Dispatchers.IO) {
val context = this@DocumentActivity
val list = when (type) {
TYPE_ALL -> getAllDocument(this@DocumentActivity)
else -> getAllDocument(this@DocumentActivity)
TYPE_ALL -> getAllDocument(context)
TYPE_PDF -> getPdfDocument(context)
TYPE_WORD -> getWordDocument(context)
TYPE_EXCEL -> getExcelDocument(context)
TYPE_PPT -> getPptDocument(context)
else -> getAllDocument(context)
}
if (list.isEmpty()) {
} else {
launch(Dispatchers.Main) {
if (list.isEmpty()) {
adapter?.submitList(listOf())
} else {
adapter?.submitList(list)
}
}
}
}
\ No newline at end of file
......@@ -28,6 +28,31 @@ import java.io.File
import java.io.FileOutputStream
import java.io.IOException
/**
* 全局数据数据
*/
fun getGlobalAllList(): ArrayList<DocumentBean> {
val arrayListOf = arrayListOf<DocumentBean>()
arrayListOf.addAll(GlobalPdfList)
arrayListOf.addAll(GlobalWordList)
arrayListOf.addAll(GlobalExcelList)
arrayListOf.addAll(GlobalPptList)
return arrayListOf
}
val GlobalPdfList = arrayListOf<DocumentBean>()
val GlobalWordList = arrayListOf<DocumentBean>()
var GlobalExcelList = arrayListOf<DocumentBean>()
var GlobalPptList = arrayListOf<DocumentBean>()
fun cleanGlobalData() {
GlobalPdfList.clear()
GlobalWordList.clear()
GlobalExcelList.clear()
GlobalPptList.clear()
}
fun Context.upDateDemoStore() {
val demoFile = File(filesDir, "demo")
MediaScannerConnection.scanFile(
......@@ -106,7 +131,8 @@ fun getAllDocument(context: Context): MutableList<DocumentBean> {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
//清理全局数据
cleanGlobalData()
val selectionArgs = arrayOf(
MIME_TYPE_PDF,
......@@ -121,27 +147,50 @@ fun getAllDocument(context: Context): MutableList<DocumentBean> {
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
val documentBean = DocumentBean(it.path, uri = it.uri, type = getDocumentType(it))
if (documentBean.type == TYPE_PDF) {
context.pdfCheck(documentBean)
when (documentBean.type) {
TYPE_PDF -> {
context.pdfCheck(documentBean)
GlobalPdfList.add(documentBean)
}
TYPE_WORD -> {
GlobalWordList.add(documentBean)
}
TYPE_EXCEL -> {
GlobalExcelList.add(documentBean)
}
TYPE_PPT -> {
GlobalPptList.add(documentBean)
}
}
documentBean
}
val new = documentList.toMutableList()
val pptDemo = getPPtDemo(context)
if (File(pptDemo.path).exists()) {
new.add(0, pptDemo)
GlobalPptList.add(0, pptDemo)
}
val excelDemo = getExcelDemo(context)
if (File(excelDemo.path).exists()) {
new.add(0, excelDemo)
GlobalExcelList.add(0, excelDemo)
}
val wordDemp = getWordDemo(context)
if (File(wordDemp.path).exists()) {
new.add(0, wordDemp)
GlobalWordList.add(0, wordDemp)
}
val pdfDemo = getPdfDemo(context)
if (File(pdfDemo.path).exists()) {
context.pdfCheck(pdfDemo)
new.add(0, pdfDemo)
GlobalPdfList.add(0, pdfDemo)
}
return new
}
......@@ -164,6 +213,8 @@ fun getPdfDocument(context: Context): MutableList<DocumentBean> {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
GlobalPdfList.clear()
val selectionArgs = arrayOf(
MIME_TYPE_PDF
)
......@@ -171,12 +222,14 @@ fun getPdfDocument(context: Context): MutableList<DocumentBean> {
val documentList = list.map {
val demoDocumentBean = DocumentBean(it.path, uri = it.uri, type = TYPE_PDF)
context.pdfCheck(demoDocumentBean)
GlobalPdfList.add(demoDocumentBean)
demoDocumentBean
}
val new = documentList.toMutableList()
val pdfDemo = getPdfDemo(context)
if (File(pdfDemo.path).exists()) {
new.add(0, pdfDemo)
GlobalPdfList.add(0, pdfDemo)
}
return new
}
......@@ -186,18 +239,22 @@ fun getWordDocument(context: Context): MutableList<DocumentBean> {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
GlobalWordList.clear()
val selectionArgs = arrayOf(
MIME_TYPE_DOC,
MIME_TYPE_DOCX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
DocumentBean(it.path, uri = it.uri, type = TYPE_WORD)
val document = DocumentBean(it.path, uri = it.uri, type = TYPE_WORD)
GlobalWordList.add(document)
document
}
val new = documentList.toMutableList()
val wordDemo = getWordDemo(context)
if (File(wordDemo.path).exists()) {
new.add(0, wordDemo)
GlobalWordList.add(0, wordDemo)
}
return new
}
......@@ -207,18 +264,23 @@ fun getExcelDocument(context: Context): MutableList<DocumentBean> {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
GlobalExcelList.clear()
val selectionArgs = arrayOf(
MIME_TYPE_XLS,
MIME_TYPE_XLSX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
DocumentBean(it.path, uri = it.uri, type = TYPE_EXCEL)
val document = DocumentBean(it.path, uri = it.uri, type = TYPE_EXCEL)
GlobalExcelList.add(document)
document
}
val new = documentList.toMutableList()
val excelDemo = getExcelDemo(context)
if (File(excelDemo.path).exists()) {
new.add(0, excelDemo)
GlobalExcelList.add(0, excelDemo)
}
return new
}
......@@ -228,18 +290,22 @@ fun getPptDocument(context: Context): MutableList<DocumentBean> {
context.saveAssetsFile()
ConstObject.haveSaveDemo = true
}
GlobalPptList.clear()
val selectionArgs = arrayOf(
MIME_TYPE_PPT,
MIME_TYPE_PPTX,
)
val list = context.getMediaFile(selectionArgs = selectionArgs)
val documentList = list.map {
DocumentBean(it.path, uri = it.uri, type = TYPE_PPT)
val document = DocumentBean(it.path, uri = it.uri, type = TYPE_PPT)
GlobalPptList.add(document)
document
}
val new = documentList.toMutableList()
val pptDemo = getPPtDemo(context)
if (File(pptDemo.path).exists()) {
new.add(0, pptDemo)
GlobalPptList.add(0, pptDemo)
}
return new
}
......
......@@ -30,6 +30,7 @@ class HomeAdapter() : BaseQuickAdapter<HomeUIBean, HomeAdapter.HomeUIBeanViewHol
binding.ivIcon.setImageResource(item.icon)
binding.tvDes.text = item.des
if (item.fileNumber != -1) {
binding.tvFileNumber.visibility = View.VISIBLE
binding.tvFileNumber.text = "${item.fileNumber} files"
}
binding.root.setOnClickListener {
......@@ -42,6 +43,7 @@ class HomeAdapter() : BaseQuickAdapter<HomeUIBean, HomeAdapter.HomeUIBeanViewHol
binding.ivIcon.setImageResource(item.icon)
binding.tvDes.text = item.des
if (item.fileNumber != -1) {
binding.tvFileNumber.visibility = View.VISIBLE
binding.tvFileNumber.text = "${item.fileNumber} files"
}
binding.root.setOnClickListener {
......
......@@ -6,6 +6,7 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import com.base.pdfoneread.R
import com.base.pdfoneread.bean.DocumentBean.Companion.TYPE_ALL
......@@ -28,10 +29,20 @@ import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_GRID
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_LIST
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_TITTLE
import com.base.pdfoneread.ui.document.DocumentActivity
import com.base.pdfoneread.ui.document.GlobalExcelList
import com.base.pdfoneread.ui.document.GlobalPdfList
import com.base.pdfoneread.ui.document.GlobalPptList
import com.base.pdfoneread.ui.document.GlobalWordList
import com.base.pdfoneread.ui.document.getAllDocument
import com.base.pdfoneread.ui.document.getGlobalAllList
import com.base.pdfoneread.utils.LogEx
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class HomeFragment() : Fragment() {
private val TAG = "HomeFragment"
private lateinit var binding: FragmentHomeBinding
private val adapter: HomeAdapter = HomeAdapter()
......@@ -83,9 +94,36 @@ class HomeFragment() : Fragment() {
binding.swipeRefreshLayout.setOnRefreshListener {
refreshData()
}
refreshData()
}
private fun refreshData() {
fun refreshData() {
kotlin.runCatching {
lifecycleScope.launch(Dispatchers.IO) {
getAllDocument(requireContext())
launch(Dispatchers.Main) {
val all = groupList.find { it.key == KEY_ALL }
LogEx.logDebug(TAG, "KEY_ALL ${getGlobalAllList().size} all=${all?.key}")
all?.fileNumber = getGlobalAllList().size
val pdf = groupList.find { it.key == KEY_PDF }
pdf?.fileNumber = GlobalPdfList.size
val word = groupList.find { it.key == KEY_WORD }
word?.fileNumber = GlobalWordList.size
val excel = groupList.find { it.key == KEY_EXCEL }
excel?.fileNumber = GlobalExcelList.size
val ppt = groupList.find { it.key == KEY_PPT }
ppt?.fileNumber = GlobalPptList.size
adapter.submitList(groupList)
binding.swipeRefreshLayout.isRefreshing = false
}
}
}
}
......
......@@ -5,6 +5,7 @@ import android.graphics.Color
import androidx.activity.addCallback
import androidx.core.view.updatePadding
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import androidx.navigation.NavController
import androidx.navigation.fragment.NavHostFragment
import com.base.pdfoneread.R
......@@ -12,9 +13,14 @@ import com.base.pdfoneread.databinding.ActivityMainBinding
import com.base.pdfoneread.ui.BaseActivity
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_GRID
import com.base.pdfoneread.bean.HomeUIBean.Companion.UI_TYPE_LIST
import com.base.pdfoneread.ui.document.getAllDocument
import com.base.pdfoneread.ui.views.MainDialog.showAppExitDialog
import com.base.pdfoneread.ui.views.MainDialog.showStoragePermission
import com.base.pdfoneread.utils.BarUtils
import com.base.pdfoneread.utils.PermissionUtils.checkStorePermission
import com.base.pdfoneread.utils.SpannableUtils.colorSpanner
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MainActivity : BaseActivity<ActivityMainBinding>() {
......@@ -37,6 +43,18 @@ class MainActivity : BaseActivity<ActivityMainBinding>() {
navController = navHostFragment.navController
changeHomeRvIcon()
if (!checkStorePermission()) {
showStoragePermission(launcher) { refreshHomeData() }
}
}
private fun refreshHomeData() {
val fragment = getNavCurrentFragment()
if (fragment is HomeFragment) {
fragment.refreshData()
}
}
override fun initListener() {
......
......@@ -11,56 +11,58 @@ import android.view.View
import com.base.pdfoneread.R
import com.base.pdfoneread.ads.admob.AdmobNativeUtils
import com.base.pdfoneread.databinding.DialogAppExitBinding
import com.base.pdfoneread.databinding.DialogStoragePermissionBinding
import com.base.pdfoneread.utils.ActivityLauncher
import com.base.pdfoneread.utils.PermissionUtils.requestStoragePermission
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
object MainDialog {
// fun Context.showStoragePermission(
// launcher: ActivityLauncher,
// launcherAction: ((flag: Boolean) -> Unit)? = null,
// noLauncherAction: (() -> Unit)? = null,
// dismissAction: (() -> Unit)? = null,
// ): BottomSheetDialog {
// val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
// val binding = DialogStoragePermissionBinding.inflate(LayoutInflater.from(this))
// dialog.setContentView(binding.root)
// dialog.setCanceledOnTouchOutside(true)
//
// dialog.show()
//
// val parentView = binding.root.parent as View
// val behavior = BottomSheetBehavior.from(parentView)
// //展开
// behavior.state = BottomSheetBehavior.STATE_EXPANDED
//
// binding.tvAllow.setOnClickListener {
// dialog.dismiss()
// requestStoragePermission(launcher) {
// launcherAction?.invoke(it)
// }
// }
// dialog.setOnDismissListener {
// dismissAction?.invoke()
// }
// val text = "To read and edit documents on your device, please allow PDF Reader to access all your files"
// val redText = "PDF Reader"
// val spannableString = SpannableString(text)
// val startIndex = text.indexOf(redText)
// val endIndex = startIndex + redText.length
//
// spannableString.setSpan(
// ForegroundColorSpan(Color.parseColor("#6DA9FD")),
// startIndex,
// endIndex,
// Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
// )
// binding.tvTip.text = spannableString
//
// return dialog
//
// }
fun Context.showStoragePermission(
launcher: ActivityLauncher,
launcherAction: ((flag: Boolean) -> Unit)? = null,
noLauncherAction: (() -> Unit)? = null,
dismissAction: (() -> Unit)? = null,
): BottomSheetDialog {
val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
val binding = DialogStoragePermissionBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(true)
dialog.show()
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
binding.tvAllow.setOnClickListener {
dialog.dismiss()
requestStoragePermission(launcher) {
launcherAction?.invoke(it)
}
}
dialog.setOnDismissListener {
dismissAction?.invoke()
}
val text = "To read and edit documents on your device, please allow PDF Reader to access all your files"
val redText = "PDF Reader"
val spannableString = SpannableString(text)
val startIndex = text.indexOf(redText)
val endIndex = startIndex + redText.length
spannableString.setSpan(
ForegroundColorSpan(Color.parseColor("#E42803")),
startIndex,
endIndex,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
)
binding.tvTip.text = spannableString
return dialog
}
fun Activity.showAppExitDialog() {
val dialog = BottomSheetDialog(this, R.style.BottomSheetDialog)
......
package com.base.pdfoneread.utils
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.Settings
import androidx.core.app.ActivityCompat
object PermissionUtils {
fun Context.checkStorePermission(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
Environment.isExternalStorageManager()
} else {
val readPermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
val writePermission = ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
return readPermission == PackageManager.PERMISSION_GRANTED && writePermission == PackageManager.PERMISSION_GRANTED;
}
}
/**
* 检查通知权限是否拒绝
*/
fun Context.checkNotificationPermissionDenied(): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.checkSelfPermission(this, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_DENIED
} else {
return false
}
}
fun Context.requestStoragePermission(
launcher: ActivityLauncher,
jumpAction: (() -> Unit)? = null,
result: (flag: Boolean) -> Unit
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
val intent =
Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.addCategory("android.intent.category.DEFAULT")
intent.data = Uri.parse("package:${packageName}")
jumpAction?.invoke()
launcher.launch(intent) {
result.invoke(checkStorePermission())
}
} else {
launcher.launch(arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE)) { map ->
result(map.values.all { it })
}
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#FD5910" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<stroke
android:width="1dp"
android:color="#8E95A0" />
<corners android:radius="10dp" />
</shape>
\ No newline at end of file
......@@ -117,6 +117,7 @@
android:id="@+id/rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:listitem="@layout/item_document" />
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/bg_ffffff_tlr15"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="42dp"
android:src="@mipmap/permissions"
tools:ignore="ContentDescription" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="24dp"
android:text="@string/permission_required"
android:textColor="#333333"
android:textSize="20sp"
android:textStyle="bold"
tools:ignore="HardcodedText" />
<TextView
android:id="@+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="16dp"
android:gravity="start"
android:textColor="#666666"
android:textSize="16sp"
tools:ignore="HardcodedText"
tools:text="To read and edit documents on your device, please allow PDF Reader to access all your files" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_gravity="center_vertical"
android:layout_marginHorizontal="24dp"
android:layout_marginTop="38dp"
android:background="@drawable/bg_stroke_8e95a0_10">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginStart="15dp"
android:includeFontPadding="false"
android:text="@string/allow_access_to_manage_all_files"
android:textColor="@color/black"
android:textSize="15sp"
android:textStyle="bold" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="6dp"
android:src="@mipmap/icon_switch"
tools:ignore="ContentDescription" />
</FrameLayout>
<TextView
android:id="@+id/tv_allow"
android:layout_width="338dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:layout_marginTop="20dp"
android:layout_marginBottom="34dp"
android:background="@drawable/bg_ff5910_10"
android:gravity="center"
android:text="@string/allow"
android:textColor="@color/white"
android:textSize="18sp"
tools:ignore="HardcodedText" />
</LinearLayout>
\ No newline at end of file
......@@ -33,7 +33,6 @@
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="8dp"
android:visibility="gone"
tools:text="35 files" />
</LinearLayout>
\ No newline at end of file
......@@ -17,5 +17,8 @@
<string name="excel_files">Excel files</string>
<string name="ppt_files">PPT files</string>
<string name="exit">Exit</string>
<string name="permission_required">Permission Required</string>
<string name="allow">Allow</string>
<string name="allow_access_to_manage_all_files">Allow access to manage all files</string>
</resources>
\ No newline at end of file
/build
\ No newline at end of file
plugins {
id 'com.android.library'
id 'org.jetbrains.kotlin.android'
}
android {
namespace 'com.cherry.lib.doc'
compileSdk 34
defaultConfig {
minSdk 21
targetSdk 34
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.1'
implementation 'com.google.android.material:material:1.5.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.3"
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.3'
implementation "androidx.lifecycle:lifecycle-runtime-ktx:2.4.1"
implementation "androidx.lifecycle:lifecycle-common:2.4.1"
implementation("io.coil-kt:coil:1.4.0")
implementation 'org.apache.poi:poi-scratchpad:3.17'
// read file
implementation 'commons-io:commons-io:2.0.1'
// AndroidUtilCode工具类:https://github.com/Blankj/AndroidUtilCode
implementation('com.blankj:utilcodex:1.31.1')
// 文件编码判断:https://mvnrepository.com/artifact/com.googlecode.juniversalchardet/juniversalchardet
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
package com.cherry.lib.doc
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.cherry.lib.doc.test", appContext.packageName)
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity android:name=".DocViewerActivity" />
</application>
</manifest>
\ No newline at end of file
package com.cherry.lib.doc
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.appcompat.app.AppCompatActivity
import com.cherry.lib.doc.bean.DocEngine
import com.cherry.lib.doc.util.Constant
import com.cherry.lib.doc.widget.DocView
open class DocViewerActivity : AppCompatActivity() {
private val TAG = "DocViewerActivity"
companion object {
fun launchDocViewer(
activity: AppCompatActivity, docSourceType: Int, path: String?,
fileType: Int? = null, engine: Int? = null
) {
val intent = Intent(activity, DocViewerActivity::class.java)
intent.putExtra(Constant.INTENT_SOURCE_KEY, docSourceType)
intent.putExtra(Constant.INTENT_DATA_KEY, path)
intent.putExtra(Constant.INTENT_TYPE_KEY, fileType)
intent.putExtra(Constant.INTENT_ENGINE_KEY, engine)
activity.startActivity(intent)
}
}
var docSourceType = 0
var fileType = -1
var engine: Int = DocEngine.INTERNAL.value
var docUrl: String? = null// 文件地址
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_doc_viewer)
initView()
initData(intent)
}
fun initView() {
}
fun initData(intent: Intent?) {
docUrl = intent?.getStringExtra(Constant.INTENT_DATA_KEY)
docSourceType = intent?.getIntExtra(Constant.INTENT_SOURCE_KEY, 0) ?: 0
fileType = intent?.getIntExtra(Constant.INTENT_TYPE_KEY, -1) ?: -1
engine = intent?.getIntExtra(Constant.INTENT_ENGINE_KEY, DocEngine.INTERNAL.value) ?: DocEngine.INTERNAL.value
findViewById<DocView>(R.id.mDocView).openDoc(
this,
docUrl,
docSourceType,
fileType, false)
Log.e(TAG, "initData-docUrl = $docUrl")
Log.e(TAG, "initData-docSourceType = $docSourceType")
Log.e(TAG, "initData-fileType = $fileType")
}
}
\ No newline at end of file
package com.cherry.lib.doc.bean
/**
* Created by Rajat on 11,July,2020
*/
enum class DocEngine(val value: Int) {
INTERNAL(100),
MICROSOFT(200),
XDOC(300),
GOOGLE(400)
}
\ No newline at end of file
package com.cherry.lib.doc.bean
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: DocMovingOrientation
* Author: Victor
* Date: 2023/11/02 20:08
* Description:
* -----------------------------------------------------------------
*/
enum class DocMovingOrientation(val orientation: Int) {
HORIZONTAL(0),
VERTICAL(1)
}
\ No newline at end of file
package com.cherry.lib.doc.bean
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: DocSourceType
* Author: Victor
* Date: 2023/09/28 16:02
* Description:
* -----------------------------------------------------------------
*/
object DocSourceType {
const val URL = 1//在线
const val URI = 2//文件选择
const val PATH = 3//sdcard
const val ASSETS = 4//assests
}
\ No newline at end of file
package com.cherry.lib.doc.bean
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: FileType
* Author: Victor
* Date: 2023/10/25 16:11
* Description:
* -----------------------------------------------------------------
*/
object FileType {
const val TXT = 1
const val PDF = 2
const val IMAGE = 3
const val DOC = 4
const val DOCX = 5
const val XLS = 6
const val XLSX = 7
const val PPT = 8
const val PPTX = 9
const val NOT_SUPPORT = 10
}
\ No newline at end of file
package com.cherry.lib.doc.interfaces
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: OnPdfPageChangeListener
* Author: Victor
* Date: 2023/10/31 11:12
* Description:
* -----------------------------------------------------------------
*/
interface OnDocPageChangeListener {
fun OnPageChanged(foundPosition: Int, totalPageCount: Int)
}
\ No newline at end of file
package com.cherry.lib.doc.interfaces
import android.content.Context
import kotlinx.coroutines.CoroutineScope
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: OnDownloadListener
* Author: Victor
* Date: 2023/10/31 10:55
* Description:
* -----------------------------------------------------------------
*/
interface OnDownloadListener {
fun getDownloadContext(): Context
fun onDownloadStart() {}
fun onDownloadProgress(currentBytes: Long, totalBytes: Long) {}
fun onDownloadSuccess(absolutePath: String) {}
fun onError(error: Throwable) {}
fun getCoroutineScope(): CoroutineScope
}
\ No newline at end of file
package com.cherry.lib.doc.interfaces
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: OnPdfItemClickListener
* Author: Victor
* Date: 2024/02/22 17:15
* Description:
* -----------------------------------------------------------------
*/
interface OnPdfItemClickListener {
fun OnPdfItemClick(position: Int)
}
\ No newline at end of file
package com.cherry.lib.doc.interfaces
/*
* -----------------------------------------------------------------
* Copyright (C) 2018-2028, by Victor, All rights reserved.
* -----------------------------------------------------------------
* File: OnWebLoadListener
* Author: Victor
* Date: 2023/10/31 11:06
* Description:
* -----------------------------------------------------------------
*/
interface OnWebLoadListener {
fun OnWebLoadProgress(progress: Int)
fun onTitle(title: String?)
}
\ No newline at end of file
package com.cherry.lib.doc.office;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import com.blankj.utilcode.util.AppUtils;
import com.cherry.lib.doc.office.common.IOfficeToPicture;
import com.cherry.lib.doc.office.constant.EventConstant;
import com.cherry.lib.doc.office.constant.wp.WPViewConstant;
import com.cherry.lib.doc.office.res.ResKit;
import com.cherry.lib.doc.office.system.IMainFrame;
import com.cherry.lib.doc.office.system.MainControl;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
/**
* Created by zjt on 18-8-11.
*/
public abstract class IOffice implements IMainFrame {
private String TAG = "IOffice";
private MainControl control;
private boolean writeLog = true;
//view background
private Object bg = Color.LTGRAY;
private String tempFilePath;
public IOffice() {
initControl();
}
private void initControl() {
control = new MainControl(this);
control.setOffictToPicture(new IOfficeToPicture() {
public Bitmap getBitmap(int componentWidth, int componentHeight) {
if (componentWidth == 0 || componentHeight == 0) {
return null;
}
if (bitmap == null || bitmap.getWidth() != componentWidth || bitmap.getHeight() != componentHeight) {
// custom picture size
if (bitmap != null) {
bitmap.recycle();
}
bitmap = Bitmap.createBitmap((int) (componentWidth), (int) (componentHeight), Bitmap.Config.ARGB_8888);
}
return bitmap;
}
public void callBack(Bitmap bitmap) {
saveBitmapToFile(bitmap);
}
private Bitmap bitmap;
@Override
public void setModeType(byte modeType) {
}
@Override
public byte getModeType() {
return VIEW_CHANGE_END;
}
@Override
public boolean isZoom() {
return false;
}
@Override
public void dispose() {
}
});
}
private void saveBitmapToFile(Bitmap bitmap) {
Log.e(TAG,"saveBitmapToFile1");
if (bitmap == null) {
Log.e(TAG,"saveBitmapToFile2");
return;
}
if (tempFilePath == null) {
Log.e(TAG,"saveBitmapToFile3");
// 存在外部目录相册中会显示
// String state = Environment.getExternalStorageState();
// if (Environment.MEDIA_MOUNTED.equals(state)) {
// tempFilePath = Environment.getExternalStorageDirectory().getAbsolutePath();
// }
tempFilePath = "/data/data/" + AppUtils.getAppPackageName() + "/cache";
File file = new File(tempFilePath + File.separatorChar + "tempPic");
if (!file.exists()) {
file.mkdir();
}
tempFilePath = file.getAbsolutePath();
}
File file = new File(tempFilePath + File.separatorChar + "export_image.jpg");
try {
if (file.exists()) {
Log.e(TAG,"saveBitmapToFile4");
file.delete();
}
file.createNewFile();
FileOutputStream fOut = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
fOut.flush();
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public View getView() {
return control.getView();
}
public void openFile(String filepath, int docSourceType, String fileType) {
getControl().openFile(filepath, docSourceType, fileType);
}
/**
* true: show message when zooming
* false: not show message when zooming
*
* @return
*/
public boolean isShowZoomingMsg() {
return true;
}
/**
* true: pop up dialog when throw err
* false: not pop up dialog when throw err
*
* @return
*/
public boolean isPopUpErrorDlg() {
return true;
}
@Override
public abstract Activity getActivity();
/**
* do action,this is method don't call <code>control.actionEvent</code> method, Easily lead to infinite loop
*
* @param actionID action ID
* @param obj acValue
* @return True if the listener has consumed the event, false otherwise.
*/
public boolean doActionEvent(int actionID, Object obj) {
Log.e(TAG, "doActionEvent actionID" + actionID);
try {
switch (actionID) {
case EventConstant.SYS_UPDATE_TOOLSBAR_BUTTON_STATUS: //update toolsbar state
updateToolsbarStatus();
break;
case EventConstant.APP_FINDING:
String content = ((String) obj).trim();
if (content.length() > 0 && control.getFind().find(content)) {
setFindBackForwardState(true);
}
break;
case EventConstant.SS_CHANGE_SHEET:
break;
default:
return false;
}
} catch (Exception e) {
control.getSysKit().getErrorKit().writerLog(e);
}
return true;
}
@Override
public void updateToolsbarStatus() {
}
@Override
public void setFindBackForwardState(boolean state) {
}
/**
*
*/
public int getBottomBarHeight() {
return 0;
}
/**
*
*/
public int getTopBarHeight() {
return 0;
}
public boolean onEventMethod(View v, MotionEvent e1, MotionEvent e2, float xValue, float yValue, byte eventMethodType) {
return false;
}
public void changePage() {
}
public MainControl getControl() {
return this.control;
}
/**
*
*/
public abstract String getAppName();
public abstract int getMovingOrientation();
/**
* 是否绘制页码
*/
public boolean isDrawPageNumber() {
return false;
}
/**
* 是否支持zoom in / zoom out
*/
public boolean isTouchZoom() {
return true;
}
/**
* Word application 默认视图(Normal or Page)
*
* @return WPViewConstant.PAGE_ROOT or WPViewConstant.NORMAL_ROOT
*/
public byte getWordDefaultView() {
return WPViewConstant.PAGE_ROOT;
}
/**
* normal view, changed after zoom bend, you need to re-layout
*
* @return true re-layout
* false don't re-layout
*/
public boolean isZoomAfterLayoutForWord() {
return true;
}
/**
*
*/
public void changeZoom() {
}
/**
*
*/
public void error(int errorCode) {
}
@Override
public void showProgressBar(boolean visible) {
}
@Override
public void updateViewImages(List<Integer> viewList) {
}
/**
* when need destroy the office engine instance callback this method
*/
public void destroyEngine() {
}
/**
* get Internationalization resource
*
* @param resName Internationalization resource name
*/
public String getLocalString(String resName) {
return ResKit.instance().getLocalString(resName);
}
@Override
public boolean isShowPasswordDlg() {
return true;
}
@Override
public boolean isShowProgressBar() {
return true;
}
@Override
public boolean isShowFindDlg() {
return true;
}
@Override
public boolean isShowTXTEncodeDlg() {
return true;
}
/**
*
*/
public String getTXTDefaultEncode() {
return "GBK";
}
@Override
public void completeLayout() {
}
@Override
public boolean isChangePage() {
return true;
}
/**
* @param saveLog
*/
public void setWriteLog(boolean saveLog) {
this.writeLog = saveLog;
}
/**
* @return
*/
public boolean isWriteLog() {
return writeLog;
}
@Override
public void setThumbnail(boolean isThumbnail) {
}
@Override
public boolean isThumbnail() {
return false;
}
/**
* get view backgrouond
*
* @return
*/
public Object getViewBackground() {
return bg;
}
/**
* set flag whether fitzoom can be larger than 100% but smaller than the max zoom
*
* @param ignoreOriginalSize
*/
public void setIgnoreOriginalSize(boolean ignoreOriginalSize) {
}
/**
* @return true fitzoom may be larger than 100% but smaller than the max zoom
* false fitzoom can not larger than 100%
*/
public boolean isIgnoreOriginalSize() {
return false;
}
public int getPageListViewMovingPosition() {
return getMovingOrientation();
}
/**
* @return
*/
public abstract File getTemporaryDirectory();
/**
* 释放内存
*/
public void dispose() {
if (control != null) {
control.dispose();
control = null;
}
}
}
\ No newline at end of file
/*
* 文件名称: CriticalLock.java
*
* 编译器: android2.2
* 时间: 上午10:22:11
*/
package com.cherry.lib.doc.office.common;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* TODO: 文件注释
* <p>
* <p>
* Read版本: Read V1.0
* <p>
* 作者: jqin
* <p>
* 日期: 2011-12-12
* <p>
* 负责人: jqin
* <p>
* 负责小组:
* <p>
* <p>
*/
public class CriticalLock
{
private CriticalLock()
{
}
public static void lock()
{
reentrantLock.lock();
}
public static void unlock()
{
reentrantLock.unlock();
}
private static Lock reentrantLock = new ReentrantLock();
}
/*
* 文件名称: ICustomDialog.java
*
* 编译器: android2.2
* 时间: 下午12:47:14
*/
package com.cherry.lib.doc.office.common;
public interface ICustomDialog
{
//password dialog
public static final byte DIALOGTYPE_PASSWORD = 0;
//txt encode dialog
public static final byte DIALOGTYPE_ENCODE = 1;
//loading dialog
public static final byte DIALOGTYPE_LOADING = 2;
//error dialog
public static final byte DIALOGTYPE_ERROR = 3;
//
public static final byte DIALOGTYPE_FIND = 4;
/**
*
* @param type dialog type
*/
public void showDialog(byte type);
/**
*
* @param type
*/
public void dismissDialog(byte type);
}
/*
* 文件名称: OfficeToPicture.java
*
* 编译器: android2.2
* 时间: 下午2:15:37
*/
package com.cherry.lib.doc.office.common;
import android.graphics.Bitmap;
/**
* Office 文档转换成图片的接口
* <p>
* <p>
* Read版本: Read V1.0
* <p>
* 作者: ljj8494
* <p>
* 日期: 2012-5-14
* <p>
* 负责人: ljj8494
* <p>
* 负责小组:
* <p>
* <p>
*/
public interface IOfficeToPicture
{
// 实现IOfficeToPicture接口的类路径
public static final String INSTANCE_CLASS_PATH = "com.cherry.lib.doc.office.officereader.OfficeToPicture";
// 视图发生变化时生成picture,例如滚动、fling进行中
public static final byte VIEW_CHANGING = 0;
// 视图发生变化结束后,例如滚动、fling、横竖屏切换结束后
public static final byte VIEW_CHANGE_END = VIEW_CHANGING + 1;
/**
* set mode type
* @param modeType
*/
public void setModeType(byte modeType);
/**
* 生成picture模式
*
* @ return = 0,视图发生变化时生成picture,例如滚动、fling进行中,
* = 1,视图发生变化结束后,例如滚动、fling、横竖屏切换结束后。
*/
public byte getModeType();
/**
* 获得converter to picture的Bitmap,如果返回空,则不生成picture
*
* @param visibleWidth engine组件的可视图宽度
* @param visibleHeight engine组件的可视图高度
* @return Bitmap Bitmap实例
*/
public Bitmap getBitmap(int visibleWidth, int visibleHeight);
/**
* picture 绘制完成,回调方法
*
* @param bitmap 绘制好的图片
*/
public void callBack(Bitmap bitmap);
/**
* 是否以zoom方式生成picture,此zoom是指office engine的size 和 bitmap size 之间的zoom。
* 例如 engine的size 1280 * 768,而bitmap size要求是845 * 480,这样的情况是否需要zoom。
*
* @return true do zoom
* false don’t zoom
*/
public boolean isZoom();
/**
*
*/
public void dispose();
}
/*
* 文件名称: ISlideShow.java
*
* 编译器: android2.2
* 时间: 上午9:58:39
*/
package com.cherry.lib.doc.office.common;
public interface ISlideShow
{
//slideshow type
//begin slideshow
public static final byte SlideShow_Begin = 0; //0
//exit slideshow
public static final byte SlideShow_Exit = SlideShow_Begin + 1; //1
//previous step of animation
public static final byte SlideShow_PreviousStep = SlideShow_Exit + 1; //2
//next step of animation
public static final byte SlideShow_NextStep = SlideShow_PreviousStep + 1;//3
//previous slide
public static final byte SlideShow_PreviousSlide = SlideShow_NextStep + 1;//4
//next slide
public static final byte SlideShow_NextSlide = SlideShow_PreviousSlide + 1;//5
// /**
// *
// * @param actionType
// */
// public void slideshow(byte actionType);
/**
* exit slideshow
*/
public void exit();
}
/*
* 文件名称: PaintKit.java
*
* 编译器: android2.2
* 时间: 下午1:42:18
*/
package com.cherry.lib.doc.office.common;
import com.cherry.lib.doc.office.constant.SSConstant;
import android.graphics.Paint;
import android.graphics.Typeface;
/**
* TODO: 文件注释
* <p>
* <p>
* Read版本: Read V1.0
* <p>
* 作者: jqin
* <p>
* 日期: 2011-12-7
* <p>
* 负责人: jqin
* <p>
* 负责小组:
* <p>
* <p>
*/
public class PaintKit
{
private Paint paint = null;
private static PaintKit pk = new PaintKit();
/**
*
*/
private PaintKit()
{
paint = new Paint();
paint.setTextSize(SSConstant.HEADER_TEXT_FONTSZIE);
paint.setTypeface(Typeface.SERIF);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
paint.setStrokeCap(Paint.Cap.ROUND);
}
/**
*
* @return
*/
public static PaintKit instance()
{
return pk;
}
public Paint getPaint()
{
paint.reset();
paint.setAntiAlias(true);
return paint;
}
}
/*
* 文件名称: Scrollbar.java
*
* 编译器: android2.2
* 时间: 下午2:30:54
*/
package com.cherry.lib.doc.office.common;
import com.cherry.lib.doc.office.java.awt.Dimension;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
/**
* TODO: 文件注释
* <p>
* <p>
* Read版本: Read V1.0
* <p>
* 作者: jqin
* <p>
* 日期: 2011-12-13
* <p>
* 负责人: jqin
* <p>
* 负责小组:
* <p>
* <p>
*/
public class Scrollbar
{
private final int SCROLLBAR_SIZE = 5;
private final int SCROLLBAR_OFFBORDER = 2;
private final int SCROLLBAR_COLOR_ALPHA = 125;
// scroll bar color
private final int SCROLLBAR_COLOR = 0x8f444444;/*0x8fcecfd6;*/
public void setPageSize(int width, int height)
{
this.pageSize.setSize(width, height);
}
/**
* call setPageSize to set page size before call draw function
* @param canvas
* @param zoom
*/
public void draw(Canvas canvas, int currentX, int currentY, Paint paint)
{
Rect clip = canvas.getClipBounds();
int oldColor = paint.getColor();
int alpha = paint.getAlpha();
paint.setColor(SCROLLBAR_COLOR);
paint.setAlpha(SCROLLBAR_COLOR_ALPHA);
if(pageSize.width > clip.right)
{
drawHorizontalScrollBar(canvas, currentX, paint);
}
if(pageSize.height > clip.bottom)
{
drawVerticalScrollBar(canvas, currentY, paint);
}
paint.setColor(oldColor);
paint.setAlpha(alpha);
}
/**
*
* @param canvas
* @param zoom
*/
private void drawHorizontalScrollBar(Canvas canvas, int currentX, Paint paint)
{
Rect clip = canvas.getClipBounds();
//horizontal scroll bar length
float length = clip.right * clip.right / pageSize.width;
float pixelSteps = pageSize.width / (float)clip.right;
//find the scroll bar rect
float left = (pageSize.width / 2 - currentX) / pixelSteps - length / 2;
rect.set(left, clip.bottom - SCROLLBAR_SIZE - SCROLLBAR_OFFBORDER, left + length, clip.bottom - SCROLLBAR_OFFBORDER);
canvas.drawRoundRect(rect, SCROLLBAR_SIZE / 2, SCROLLBAR_SIZE / 2, paint);
}
/**
*
* @param canvas
* @param zoom
*/
private void drawVerticalScrollBar(Canvas canvas, int currentY, Paint paint)
{
Rect clip = canvas.getClipBounds();
//vertical scroll bar length
float length = clip.bottom * clip.bottom / pageSize.height;
float pixelSteps = pageSize.height / (float)clip.bottom;
//find the scroll bar rect
float top = (pageSize.height / 2 - currentY) / pixelSteps - length / 2;
rect.set(clip.right - SCROLLBAR_SIZE - SCROLLBAR_OFFBORDER, top, clip.right - SCROLLBAR_OFFBORDER, top + length);
canvas.drawRoundRect(rect, SCROLLBAR_SIZE / 2, SCROLLBAR_SIZE / 2, paint);
}
//
private Dimension pageSize = new Dimension();
//
private RectF rect = new RectF();
}
/*
* 文件名称: PathExtend.java
*
* 编译器: android2.2
* 时间: 上午10:42:18
*/
package com.cherry.lib.doc.office.common.autoshape;
import com.cherry.lib.doc.office.common.bg.BackgroundAndFill;
import com.cherry.lib.doc.office.common.borders.Line;
import android.graphics.Path;
/**
* TODO: 文件注释
* <p>
* <p>
* Read版本: Read V1.0
* <p>
* 作者: jqin
* <p>
* 日期: 2012-9-27
* <p>
* 负责人: jqin
* <p>
* 负责小组:
* <p>
* <p>
*/
public class ExtendPath
{
public ExtendPath()
{
path = new Path();
fill = null;
}
public ExtendPath(ExtendPath extendPath)
{
path = new Path(extendPath.getPath());
fill = extendPath.getBackgroundAndFill();
hasLine = extendPath.hasLine();
line = extendPath.getLine();
isArrow = extendPath.isArrowPath();
}
public void setPath(Path path)
{
this.path = path;
}
public Path getPath()
{
return path;
}
public void setBackgroundAndFill(BackgroundAndFill fill)
{
this.fill = fill;
}
public BackgroundAndFill getBackgroundAndFill()
{
return fill;
}
/*
*
*/
public boolean hasLine()
{
return hasLine;
}
/**
*
* @param border
*/
public void setLine(boolean hasLine)
{
this.hasLine = hasLine;
if(hasLine && line == null)
{
line = new Line();
}
}
/**
*
* @return
*/
public Line getLine()
{
return line;
}
/**
*
*/
public void setLine(Line line)
{
this.line = line;
if(line != null)
{
hasLine = true;
}
else
{
hasLine = false;
}
}
public void setArrowFlag(boolean isArrow)
{
this.isArrow = isArrow;
}
public boolean isArrowPath()
{
return isArrow;
}
public void dispose()
{
path = null;
if(fill != null)
{
fill.dispose();
}
}
private Path path;
private BackgroundAndFill fill;
private boolean hasLine;
private Line line;
private boolean isArrow;
}
package com.cherry.lib.doc.office.common.autoshape.pathbuilder;
import android.graphics.Path;
import android.graphics.PointF;
public class ArrowPathAndTail
{
public void reset()
{
path = null;
tail = null;
}
public Path getArrowPath()
{
return path;
}
public void setArrowPath(Path path)
{
this.path = path;
}
public PointF getArrowTailCenter()
{
return tail;
}
public void setArrowTailCenter(float x, float y)
{
this.tail = new PointF(x, y);
}
//arrow path
private Path path;
//arrow tail center position
private PointF tail;
}
/*
* 文件名称: SimpleArrow.java
*
* 编译器: android2.2
* 时间: 下午3:07:55
*/
package com.cherry.lib.doc.office.common.autoshape.pathbuilder.arrow;
import com.cherry.lib.doc.office.common.shape.AutoShape;
import android.graphics.Rect;
/**
* TODO: LeftArrow, RightArrow, UpArrow, DownArrow, LeftRightArrow, UpDownArrow
* <p>
* <p>
* Read版本: Read V1.0
* <p>
* 作者: jqin
* <p>
* 日期: 2012-9-17
* <p>
* 负责人: jqin
* <p>
* 负责小组:
* <p>
* <p>
*/
public class ArrowPathBuilder
{
/**
* get autoshape path
* @param shape
* @param rect
* @return
*/
public static Object getArrowPath(AutoShape shape, Rect rect)
{
if(shape.isAutoShape07())
{
return LaterArrowPathBuilder.getArrowPath(shape, rect);
}
else
{
return EarlyArrowPathBuilder.getArrowPath(shape, rect);
}
}
}
package com.cherry.lib.doc.office.common.bg;
import com.cherry.lib.doc.office.system.IControl;
import android.graphics.Rect;
import android.graphics.Shader;
public abstract class AShader
{
public Shader getShader()
{
return shader;
}
public Shader createShader(IControl control, int viewIndex, Rect rect)
{
return shader;
}
public int getAlpha()
{
return alpha;
}
public void setAlpha(int alpha)
{
this.alpha = alpha;
}
/**
*
*
*/
public void dispose()
{
shader = null;
}
protected int alpha = 255;
protected Shader shader = null;
}
package com.cherry.lib.doc.office.common.bg;
public abstract class Gradient extends AShader
{
public static final int COORDINATE_LENGTH = 100;
public Gradient(int[] colors, float[] positions)
{
if(colors != null && colors.length >= 2)
{
this.colors = colors;
}
this.positions = positions;
}
public int getGradientType()
{
return type;
}
public void setGradientType(int type)
{
this.type = type;
}
public int getFocus()
{
return focus;
}
public void setFocus(int focus)
{
this.focus = focus;
}
private int type;
protected int[] colors = null;
protected float[] positions = null;
//percent
private int focus = 100;
}
package com.cherry.lib.doc.office.common.picture;
public class PictureConverterThread extends Thread
{
public PictureConverterThread(PictureConverterMgr converterMgr, String srcPath, String dstPath, String type )
{
this.converterMgr = converterMgr;
this.type = type;
this.sourPath = srcPath;
this.destPath = dstPath;
}
public void run()
{
converterMgr.convertPNG(sourPath, destPath, type, false);
}
private PictureConverterMgr converterMgr;
private String type;
private String sourPath;
private String destPath;
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment