Преглед изворни кода

ComPDFKit Demo(Android) - 1.资源前缀限定修改 2.CPDFToolBar

liuxiaolong пре 1 година
родитељ
комит
b5bd93552d
29 измењених фајлова са 500 додато и 629 уклоњено
  1. 1 1
      annotation-ctrl-demo/build.gradle
  2. 7 3
      compdfkit-tools/build.gradle
  3. 2 3
      compdfkit-tools/src/main/AndroidManifest.xml
  4. 65 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFReaderView.java
  5. 51 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFToolBar.java
  6. 0 54
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/PDFReaderView.java
  7. 68 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/task/CExtractAssetFileTask.java
  8. 50 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/CFileUtilsExtension.java
  9. 1 1
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/PDFAppGlideModule.java
  10. 0 219
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/FileUtilsExtension.java
  11. 105 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/threadpools/CThreadPoolUtils.java
  12. 0 46
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/threadpools/SimpleBackgroundTask.java
  13. 0 265
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/threadpools/ThreadPoolUtils.java
  14. 18 0
      compdfkit-tools/src/main/res/drawable/tools_ic_more.xml
  15. 9 0
      compdfkit-tools/src/main/res/drawable/tools_ic_outline.xml
  16. 9 0
      compdfkit-tools/src/main/res/drawable/tools_ic_search.xml
  17. 58 0
      compdfkit-tools/src/main/res/layout/tools_cpdf_tool_bar.xml
  18. 9 0
      compdfkit-tools/src/main/res/values/tools_attrs.xml
  19. 1 1
      edit-ctrl-demo/build.gradle
  20. 1 1
      form-ctrl-demo/build.gradle
  21. 1 1
      pageedit-ctrl-demo/build.gradle
  22. 2 4
      viewer-ctrl-demo/build.gradle
  23. 2 2
      viewer-ctrl-demo/src/main/AndroidManifest.xml
  24. 10 10
      viewer-ctrl-demo/src/main/java/com/compdfkit/demo/viewer/MainActivity.java
  25. 0 15
      viewer-ctrl-demo/src/main/res/layout/compdfkit_viewer_activity_main.xml
  26. 27 0
      viewer-ctrl-demo/src/main/res/layout/viewer_activity_main.xml
  27. 1 1
      viewer-ctrl-demo/src/main/res/values-night/themes.xml
  28. 1 1
      viewer-ctrl-demo/src/main/res/values/strings.xml
  29. 1 1
      viewer-ctrl-demo/src/main/res/values/themes.xml

+ 1 - 1
annotation-ctrl-demo/build.gradle

@@ -5,7 +5,7 @@ plugins {
 android {
     namespace 'com.compdfkit.demo.annotation'
     compileSdk rootProject.ext.android.COMPILESDK
-    resourcePrefix 'compdfkit_annotation_'
+    resourcePrefix 'annotation_'
     defaultConfig {
         applicationId "com.compdfkit.demo.annotation"
         minSdk rootProject.ext.android.MINSDK

+ 7 - 3
compdfkit-tools/build.gradle

@@ -13,7 +13,7 @@ def releaseTime() {
 android {
     namespace 'com.compdfkit.tools'
     compileSdk rootProject.ext.android.COMPILESDK
-    resourcePrefix 'compdfkit_tools_'
+    resourcePrefix 'tools_'
 
     defaultConfig {
         minSdk rootProject.ext.android.MINSDK
@@ -43,10 +43,14 @@ dependencies {
     api fileTree(include: ['*.jar'], dir: 'libs')
     api project(path:':compdfkit_repo:compdfkit')
     api project(path:':compdfkit_repo:compdfkit-ui')
-    api 'com.github.bumptech.glide:glide:4.13.2'
-    annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
+
+    api 'com.github.bumptech.glide:glide:4.14.2'
+    annotationProcessor 'com.github.bumptech.glide:compiler:4.14.2'
+
     api 'androidx.documentfile:documentfile:1.0.1'
 
     implementation 'androidx.appcompat:appcompat:1.6.1'
     implementation 'com.google.android.material:material:1.8.0'
+    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+
 }

Разлика између датотеке није приказан због своје велике величине
+ 2 - 3
compdfkit-tools/src/main/AndroidManifest.xml


+ 65 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFReaderView.java

@@ -0,0 +1,65 @@
+package com.compdfkit.tools.pdfview;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.compdfkit.core.document.CPDFDocument;
+
+
+public class CPDFReaderView extends FrameLayout {
+
+    private com.compdfkit.ui.reader.CPDFReaderView cPdfReaderView;
+
+    public CPDFReaderView(@NonNull Context context) {
+        super(context);
+        initCPDFReaderView();
+    }
+
+    public CPDFReaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        initCPDFReaderView();
+    }
+
+    public CPDFReaderView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+
+    private void initCPDFReaderView() {
+        cPdfReaderView = new com.compdfkit.ui.reader.CPDFReaderView(getContext());
+        addView(cPdfReaderView);
+    }
+
+
+    /**
+     * This method opens a PDF file located at the given file path.
+     *
+     * @param pdfFilePath The file path of the PDF file to be opened.
+     */
+    public void openPdfFile(String pdfFilePath) {
+        // Create a new instance of the CPDFDocument class, passing in the current context.
+        CPDFDocument cpdfDocument = new CPDFDocument(getContext());
+        // Attempt to open the PDF file at the given file path using the open method of the CPDFDocument class.
+        CPDFDocument.PDFDocumentError pdfDocumentError = cpdfDocument.open(pdfFilePath);
+        // Switch on the result of the open method to handle the different possible outcomes.
+        switch (pdfDocumentError) {
+            // If the PDF file was successfully opened, set the PDF document of the CPdfReaderView instance to the opened document.
+            case PDFDocumentErrorSuccess:
+                cPdfReaderView.setPDFDocument(cpdfDocument);
+                break;
+            // If the PDF file requires a password to be opened, do nothing for now.
+            case PDFDocumentErrorPassword:
+
+                break;
+            // For all other errors, do nothing for now.
+            default:
+                break;
+        }
+    }
+
+
+}

+ 51 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFToolBar.java

@@ -0,0 +1,51 @@
+package com.compdfkit.tools.pdfview;
+
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.text.TextUtils;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.appcompat.widget.AppCompatTextView;
+
+import com.compdfkit.tools.R;
+
+public class CPDFToolBar extends FrameLayout {
+
+    private AppCompatTextView tvToolBarTitle;
+
+    public CPDFToolBar(@NonNull Context context) {
+        super(context);
+        initToolBar(context, null);
+    }
+
+    public CPDFToolBar(@NonNull Context context, @Nullable AttributeSet attrs) {
+        super(context, attrs);
+        initToolBar(context, attrs);
+    }
+
+    public CPDFToolBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    private void initToolBar(Context context, @Nullable AttributeSet attrs){
+        LayoutInflater.from(getContext()).inflate(R.layout.tools_cpdf_tool_bar, this);
+        tvToolBarTitle = findViewById(R.id.tv_tool_bar_title);
+        initAttributes(context, attrs);
+    }
+
+    private void initAttributes(Context context, @Nullable AttributeSet attrs){
+        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.Tools_CPDFToolBar);
+        if (typedArray != null) {
+            String toolBarTitle = typedArray.getString(R.styleable.Tools_CPDFToolBar_tools_toolbar_title);
+            if (!TextUtils.isEmpty(toolBarTitle)) {
+                tvToolBarTitle.setText(toolBarTitle);
+            }
+        }
+    }
+
+}

+ 0 - 54
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/PDFReaderView.java

@@ -1,54 +0,0 @@
-package com.compdfkit.tools.pdfview;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.widget.FrameLayout;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.compdfkit.core.document.CPDFDocument;
-import com.compdfkit.ui.reader.CPDFReaderView;
-
-
-public class PDFReaderView extends FrameLayout {
-
-    private CPDFReaderView cPdfReaderView;
-
-    public PDFReaderView(@NonNull Context context) {
-        super(context);
-        initCPDFReaderView();
-    }
-
-    public PDFReaderView(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        initCPDFReaderView();
-    }
-
-    public PDFReaderView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-
-    private void initCPDFReaderView() {
-        cPdfReaderView = new CPDFReaderView(getContext());
-        addView(cPdfReaderView);
-    }
-
-    public void openPDFFile(String pdfFilePath) {
-        CPDFDocument cpdfDocument = new CPDFDocument(getContext());
-        CPDFDocument.PDFDocumentError pdfDocumentError = cpdfDocument.open(pdfFilePath);
-        switch (pdfDocumentError) {
-            case PDFDocumentErrorSuccess:
-                cPdfReaderView.setPDFDocument(cpdfDocument);
-                break;
-            case PDFDocumentErrorPassword:
-                break;
-            default:
-                break;
-        }
-    }
-
-
-}

+ 68 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/task/CExtractAssetFileTask.java

@@ -0,0 +1,68 @@
+
+package com.compdfkit.tools.task;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+
+import com.compdfkit.tools.utils.CFileUtilsExtension;
+import com.compdfkit.tools.utils.threadpools.CThreadPoolUtils;
+
+import java.io.File;
+
+
+public class CExtractAssetFileTask {
+
+
+    /**
+     * Extracts the file at {@code assetPath} from the app's assets into the private app directory.
+     *
+     * @param assetPath Path pointing to a file inside the app's assets.
+     * @param context Context used to retrieve the referenced file from the app's assets.
+     * @param listener A listener notified of extraction completion.
+     */
+    public static void extract(
+            @NonNull final Context context,
+            @NonNull final String assetPath,
+            @NonNull final String fileName,
+            @Nullable final OnDocumentExtractedListener listener) {
+        extract(context, assetPath, fileName, true, listener);
+    }
+
+    /**
+     * Extracts the file at {@code assetPath} from the app's assets into the private app directory.
+     *
+     * @param assetPath Path pointing to a file inside the app's assets.
+     * @param context Context used to retrieve the referenced file from the app's assets.
+     * @param overwriteExisting Whether an existing file in the private app directory should be
+     *     overwritten.
+     * @param listener A listener notified of extraction completion.
+     */
+    public static void extract(
+            @NonNull Context context,
+            @NonNull String assetPath,
+            @NonNull String fileName,
+            boolean overwriteExisting,
+            @Nullable OnDocumentExtractedListener listener) {
+        CThreadPoolUtils.getInstance().execute(()->{
+            File pdfFile = new File(context.getFilesDir().getAbsoluteFile(), fileName);
+            CFileUtilsExtension.copyFileFromAssets(context, assetPath, pdfFile.getParent(), fileName, overwriteExisting);
+            if (listener != null) {
+                listener.onDocumentExtracted(pdfFile);
+            }
+        });
+    }
+
+
+    /** Listens for document extraction events. */
+    public interface OnDocumentExtractedListener {
+        /**
+         * Called when there is a document extraction events.
+         *
+         * @param documentFile extracted {@link File}
+         */
+        void onDocumentExtracted(@NonNull File documentFile);
+    }
+}

+ 50 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/CFileUtilsExtension.java

@@ -0,0 +1,50 @@
+package com.compdfkit.tools.utils;
+
+import android.content.Context;
+import android.util.Log;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public class CFileUtilsExtension {
+
+
+
+    public static void copyFileFromAssets(Context context, String assetName, String savePath, String saveName, final boolean overwriteExisting
+    ) {
+        //if save path folder not exists, create directory
+        File dir = new File(savePath);
+        if (!dir.exists()) {
+            if (!dir.mkdir()) {
+                Log.d("FileUtils", "mkdir error: " + savePath);
+                return;
+            }
+        }
+
+        // 拷贝文件
+        String filename = savePath + "/" + saveName;
+        File file = new File(filename);
+        if (!file.exists() || overwriteExisting) {
+            try {
+                InputStream inStream = context.getAssets().open(assetName);
+                FileOutputStream fileOutputStream = new FileOutputStream(filename);
+
+                int byteread;
+                byte[] buffer = new byte[1024];
+                while ((byteread = inStream.read(buffer)) != -1) {
+                    fileOutputStream.write(buffer, 0, byteread);
+                }
+                fileOutputStream.flush();
+                inStream.close();
+                fileOutputStream.close();
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            Log.d("FileUtils", "[copyFileFromAssets] copy asset file: " + assetName + " to : " + filename);
+        } else {
+            Log.d("FileUtils", "[copyFileFromAssets] file is exist: " + filename);
+        }
+    }
+}

+ 1 - 1
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/PDFAppGlideModule.java

@@ -5,7 +5,7 @@ import com.bumptech.glide.module.AppGlideModule;
 
 
 @GlideModule
-public class PDFAppGlideModule extends AppGlideModule {
+public class CPDFAppGlideModule extends AppGlideModule {
     @Override
     public boolean isManifestParsingEnabled() {
         return false;

+ 0 - 219
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/FileUtilsExtension.java

@@ -1,219 +0,0 @@
-package com.compdfkit.tools.utils;
-
-import android.content.Context;
-import android.graphics.Bitmap;
-import android.util.Log;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-public class FileUtilsExtension {
-    private static long dir_size = 0L;
-
-    /**
-     * Return the name of file.
-     *
-     * @param file The file.
-     * @return the name of file; 根据全路径获取文件名
-     */
-    public static String getFileName(final File file) {
-        if (file == null) {
-            return null;
-        }
-        return getFileName(file.getAbsolutePath());
-    }
-
-    /**
-     * Return the name of file.
-     *
-     * @param filePath The path of file.
-     * @return the name of file; 根据全路径获取文件名
-     */
-    public static String getFileName(final String filePath) {
-        if (isSpace(filePath)) {
-            return filePath;
-        }
-        int lastSep = filePath.lastIndexOf(File.separator);
-        return lastSep == -1 ? filePath : filePath.substring(lastSep + 1);
-    }
-
-    /**
-     * Return the name of file without extension.
-     *
-     * @param file The file.
-     * @return the name of file without extension; 根据全路径获取文件名不带拓展名
-     */
-    public static String getFileNameNoExtension(final File file) {
-        if (file == null) {
-            return null;
-        }
-        return getFileNameNoExtension(file.getPath());
-    }
-
-    /**
-     * Return the name of file without extension.
-     *
-     * @param filePath The path of file.
-     * @return the name of file without extension; 根据全路径获取文件名不带拓展名
-     */
-    public static String getFileNameNoExtension(final String filePath) {
-        if (isSpace(filePath)) {
-            return filePath;
-        }
-        int lastPoi = filePath.lastIndexOf('.');
-        int lastSep = filePath.lastIndexOf(File.separator);
-        if (lastSep == -1) {
-            return (lastPoi == -1 ? filePath : filePath.substring(0, lastPoi));
-        }
-        if (lastPoi == -1 || lastSep > lastPoi) {
-            return filePath.substring(lastSep + 1);
-        }
-        return filePath.substring(lastSep + 1, lastPoi);
-    }
-
-    /**
-     * Return the extension of file.
-     *
-     * @param file The file.
-     * @return the extension of file; 根据全路径获取文件拓展名
-     */
-    public static String getFileExtension(final File file) {
-        if (file == null) {
-            return null;
-        }
-        return getFileExtension(file.getPath());
-    }
-
-    /**
-     * Return the extension of file.
-     *
-     * @param filePath The path of file.
-     * @return the extension of file ; 根据全路径获取文件拓展名
-     */
-    public static String getFileExtension(final String filePath) {
-        if (isSpace(filePath)) {
-            return filePath;
-        }
-        int lastPoi = filePath.lastIndexOf('.');
-        int lastSep = filePath.lastIndexOf(File.separator);
-        if (lastPoi == -1 || lastSep >= lastPoi) {
-            return "";
-        }
-        return filePath.substring(lastPoi + 1);
-    }
-
-    private static boolean isSpace(final String s) {
-        if (s == null) {
-            return true;
-        }
-        for (int i = 0, len = s.length(); i < len; ++i) {
-            if (!Character.isWhitespace(s.charAt(i))) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-
-    /**
-     * @description:根据文件路径得到文件大小
-     */
-    public static Long getFileSize(final String filePath) {
-        if (isSpace(filePath)) {
-            return 0L;
-        }
-        Long fileSize = new File(filePath).length();
-        return fileSize;
-    }
-
-    /**
-     * @description:保存bitmap到预制路径上
-     */
-    public static String saveSignBitmap(Context context, Bitmap mBitmap) {
-        String savePath = context.getCacheDir().getAbsolutePath();
-        File filePic;
-        try {
-            filePic = new File(savePath + File.separator + "signature" + File.separator + generateFileName() + ".png");
-            if (!filePic.exists()) {
-                filePic.getParentFile().mkdirs();
-                filePic.createNewFile();
-            }
-            FileOutputStream fos = new FileOutputStream(filePic);
-            mBitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
-            fos.flush();
-            fos.close();
-        } catch (IOException e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-            return null;
-        }
-
-        return filePic.getAbsolutePath();
-    }
-
-    /**
-     * @description:设置文件名称
-     */
-    private static String generateFileName() {
-        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
-        Date date = new Date(System.currentTimeMillis());
-        return simpleDateFormat.format(date);
-    }
-
-    /**
-     * @description:根据文件路径删除文件
-     */
-    public static boolean deleteFile(String filePath) {
-        File filePic;
-        try {
-            filePic = new File(filePath);
-            if (filePic.exists() && filePic.isFile()) {
-                return filePic.delete();
-            }
-        } catch (Exception e) {
-            // TODO Auto-generated catch block
-            e.printStackTrace();
-        }
-        return false;
-    }
-
-
-    public static void copyFileFromAssets(Context context, String assetName, String savePath, String saveName) {
-        // 若目标文件夹不存在,则创建
-        File dir = new File(savePath);
-        if (!dir.exists()) {
-            if (!dir.mkdir()) {
-                Log.d("FileUtils", "mkdir error: " + savePath);
-                return;
-            }
-        }
-
-        // 拷贝文件
-        String filename = savePath + "/" + saveName;
-        File file = new File(filename);
-        if (!file.exists()) {
-            try {
-                InputStream inStream = context.getAssets().open(assetName);
-                FileOutputStream fileOutputStream = new FileOutputStream(filename);
-
-                int byteread;
-                byte[] buffer = new byte[1024];
-                while ((byteread = inStream.read(buffer)) != -1) {
-                    fileOutputStream.write(buffer, 0, byteread);
-                }
-                fileOutputStream.flush();
-                inStream.close();
-                fileOutputStream.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
-            Log.d("FileUtils", "[copyFileFromAssets] copy asset file: " + assetName + " to : " + filename);
-        } else {
-            Log.d("FileUtils", "[copyFileFromAssets] file is exist: " + filename);
-        }
-    }
-}

+ 105 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/threadpools/CThreadPoolUtils.java

@@ -0,0 +1,105 @@
+package com.compdfkit.tools.utils.threadpools;
+
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * This class provides a thread pool implementation for executing multiple tasks concurrently.
+ */
+public class CThreadPoolUtils {
+
+    /**
+     * The number of available processors in the system.
+     */
+    private final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
+
+    /**
+     * The minimum number of threads to keep in the pool.
+     */
+    private final int CORE_POOL_SIZE = Math.max(1, CPU_COUNT - 1);
+
+    /**
+     * The maximum number of threads to allow in the pool.
+     */
+    private final int MAX_POOL_SIZE = (CPU_COUNT * 2) + 1;
+
+    /**
+     * The time to keep non-core threads alive in the pool.
+     */
+    private final int KEEP_ALIVE_TIME = 15;
+
+    /**
+     * The queue to hold tasks waiting to be executed.
+     */
+    private final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(64);
+
+    /**
+     * The thread factory used to create new threads for the pool.
+     */
+    private final ThreadFactory threadFactory = new ThreadFactory() {
+        private final AtomicInteger integer = new AtomicInteger();
+
+        @Override
+        public Thread newThread(Runnable r) {
+            return new Thread(r, "ThreadPoolUtils thread:" + integer.getAndIncrement());
+        }
+    };
+
+    /**
+     * The actual thread pool executor instance.
+     */
+    public final ThreadPoolExecutor poolExecutor;
+
+    /**
+     * Private constructor to prevent external instantiation.
+     */
+    private CThreadPoolUtils() {
+        ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
+                MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue,
+                threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
+        // Allow core threads to time out after being idle for a while.
+        mThreadPoolExecutor.allowCoreThreadTimeOut(true);
+        this.poolExecutor = mThreadPoolExecutor;
+    }
+
+    /**
+     * The singleton holder class for the thread pool instance.
+     */
+    private final static class SingleTon {
+        private final static CThreadPoolUtils instance = new CThreadPoolUtils();
+    }
+
+    /**
+     * Returns the singleton instance of the ThreadPoolUtils class.
+     *
+     * @return The singleton instance of the ThreadPoolUtils class.
+     */
+    public static synchronized CThreadPoolUtils getInstance() {
+        return SingleTon.instance;
+    }
+
+    /**
+     * Executes a single command in the thread pool.
+     *
+     * @param command The command to execute.
+     */
+    public void execute(final Runnable command) {
+        poolExecutor.execute(command);
+    }
+
+    /**
+     * Executes a list of commands in the thread pool.
+     *
+     * @param commands The list of commands to execute.
+     */
+    public void execute(final List<Runnable> commands) {
+        for (Runnable command : commands) {
+            poolExecutor.execute(command);
+        }
+    }
+}

+ 0 - 46
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/threadpools/SimpleBackgroundTask.java

@@ -1,46 +0,0 @@
-package com.compdfkit.demo.utils.threadpools;
-
-import android.app.Activity;
-import android.content.Context;
-import android.os.AsyncTask;
-
-import java.lang.ref.WeakReference;
-
-/**
- * @classname:SimpleBackgroundTask
- * @date:27/7/18 10:53
- * @description: Async异步线程处理, 主要解决对leak的处理
- */
-public abstract class SimpleBackgroundTask<T> extends AsyncTask<Void, Void, T> {
-    WeakReference<Context> weakActivity;
-
-    public SimpleBackgroundTask(Context context) {
-        weakActivity = new WeakReference<>(context);
-    }
-
-    @Override
-    protected final T doInBackground(Void... voids) {
-        return onRun();
-    }
-
-    @Override
-    protected void onPostExecute(T t) {
-        Activity activity = (Activity) weakActivity.get();
-        if ((null == activity) || activity.isFinishing() || activity.isDestroyed()) {
-            cancel(true);
-            return;
-        } else {
-            onSuccess(t);
-            cancel(true);
-        }
-    }
-
-    public SimpleBackgroundTask<T> execute() {
-        executeOnExecutor(ThreadPoolUtils.getInstance().poolExecutor);
-        return this;
-    }
-
-    abstract protected T onRun();
-
-    abstract protected void onSuccess(T result);
-}

+ 0 - 265
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/threadpools/ThreadPoolUtils.java

@@ -1,265 +0,0 @@
-package com.compdfkit.demo.utils.threadpools;
-
-import java.util.Collection;
-import java.util.List;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.TimeoutException;
-import java.util.concurrent.atomic.AtomicInteger;
-
-/**
- * 线程池按以下行为执行任务
- * 1. 当线程数小于核心线程数时,创建线程。
- * 2. 当线程数大于等于核心线程数,且任务队列未满时,将任务放入任务队列。
- * 3. 当线程数大于等于核心线程数,且任务队列已满 - 若线程数小于最大线程数,创建线程 - 若线程数等于最大线程数,抛出异常,拒绝任务
- **/
-public class ThreadPoolUtils {
-    private final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
-
-    /******  核心线程数
-     核心线程会一直存活,及时没有任务需要执行
-     当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理
-     设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭 ******/
-    //private final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4));
-    private final int CORE_POOL_SIZE = Math.max(1, CPU_COUNT - 1);
-
-    /****** 最大线程数
-     当线程数>=corePoolSize,且任务队列已满、
-     。线程池会创建新线程来处理任务
-     当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常******/
-    private final int MAX_POOL_SIZE = (CPU_COUNT * 2) + 1;
-
-    /****** 线程空闲时间
-     当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize
-     如果allowCoreThreadTimeout=true,则会直到线程数量=0******/
-    private final int KEEP_ALIVE_TIME = 15;
-
-    /******任务队列(阻塞队列)。当核心线程都被占用,且阻塞队列已满的情况下,才会开启额外线程******/
-    private final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(64);
-
-    /****** 线程工厂 ******/
-    private final ThreadFactory threadFactory = new ThreadFactory() {
-        private final AtomicInteger integer = new AtomicInteger();
-
-        @Override
-        public Thread newThread(Runnable r) {
-            return new Thread(r, "ThreadPoolUtils thread:" + integer.getAndIncrement());
-        }
-    };
-
-    /******线程池******/
-    public final ThreadPoolExecutor poolExecutor;
-
-    private ThreadPoolUtils() {
-        /****** 当线程池中的线程数量达到上限的时候,这个时候如果在添加线程的时候没有添加拒绝行为的时候会报出RejectExecutorException******/
-        ThreadPoolExecutor mThreadPoolExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
-                MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue,
-                threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
-        mThreadPoolExecutor.allowCoreThreadTimeOut(true);
-        this.poolExecutor = mThreadPoolExecutor;
-    }
-
-    private final static class SingleTon {
-        private final static ThreadPoolUtils instance = new ThreadPoolUtils();
-    }
-
-    /**
-     * The instance gets created only when it is called for first time. Lazy-loading
-     */
-    public static synchronized ThreadPoolUtils getInstance() {
-        return SingleTon.instance;
-    }
-
-    /**
-     * 在未来某个时间执行给定的命令
-     * <p>该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。</p>
-     *
-     * @param command 命令
-     */
-    public void execute(final Runnable command) {
-        poolExecutor.execute(command);
-    }
-
-    /**
-     * 在未来某个时间执行给定的命令链表
-     * <p>该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由 Executor 实现决定。</p>
-     *
-     * @param commands 命令链表
-     */
-    public void execute(final List<Runnable> commands) {
-        for (Runnable command : commands) {
-            poolExecutor.execute(command);
-        }
-    }
-
-    /**
-     * @Decreption: 移除任务
-     **/
-    public void remove(Runnable task) {
-        poolExecutor.remove(task);
-    }
-
-    /**
-     * 提交一个Callable任务用于执行
-     * <p>如果想立即阻塞任务的等待,则可以使用{@code result = exec.submit(aCallable).get();}形式的构造。</p>
-     *
-     * @param task 任务
-     * @param <T>  泛型
-     * @return 表示任务等待完成的Future, 该Future的{@code get}方法在成功完成时将会返回该任务的结果。
-     */
-    public <T> Future<T> submit(final Callable<T> task) {
-        return poolExecutor.submit(task);
-    }
-
-    /**
-     * 提交一个Runnable任务用于执行
-     *
-     * @param task   任务
-     * @param result 返回的结果
-     * @param <T>    泛型
-     * @return 表示任务等待完成的Future, 该Future的{@code get}方法在成功完成时将会返回该任务的结果。
-     */
-    public <T> Future<T> submit(final Runnable task, final T result) {
-        return poolExecutor.submit(task, result);
-    }
-
-    /**
-     * 提交一个Runnable任务用于执行
-     *
-     * @param task 任务
-     * @return 表示任务等待完成的Future, 该Future的{@code get}方法在成功完成时将会返回null结果。
-     */
-    public Future<?> submit(final Runnable task) {
-        return poolExecutor.submit(task);
-    }
-
-    /**
-     * 执行给定的任务
-     * <p>当所有任务完成时,返回保持任务状态和结果的Future列表。
-     * 返回列表的所有元素的{@link Future#isDone}为{@code true}。
-     * 注意,可以正常地或通过抛出异常来终止已完成任务。
-     * 如果正在进行此操作时修改了给定的 collection,则此方法的结果是不确定的。</p>
-     *
-     * @param tasks 任务集合
-     * @param <T>   泛型
-     * @return 表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同,每个任务都已完成。
-     * @throws InterruptedException 如果等待时发生中断,在这种情况下取消尚未完成的任务。
-     */
-    public <T> List<Future<T>> invokeAll(final Collection<? extends Callable<T>> tasks) throws InterruptedException {
-        return poolExecutor.invokeAll(tasks);
-    }
-
-    /**
-     * 执行给定的任务
-     * <p>当所有任务完成或超时期满时(无论哪个首先发生),返回保持任务状态和结果的Future列表。
-     * 返回列表的所有元素的{@link Future#isDone}为{@code true}。
-     * 一旦返回后,即取消尚未完成的任务。
-     * 注意,可以正常地或通过抛出异常来终止已完成任务。
-     * 如果此操作正在进行时修改了给定的 collection,则此方法的结果是不确定的。</p>
-     *
-     * @param tasks   任务集合
-     * @param timeout 最长等待时间
-     * @param unit    时间单位
-     * @param <T>     泛型
-     * @return 表示任务的 Future 列表,列表顺序与给定任务列表的迭代器所生成的顺序相同。如果操作未超时,则已完成所有任务。如果确实超时了,则某些任务尚未完成。
-     * @throws InterruptedException 如果等待时发生中断,在这种情况下取消尚未完成的任务
-     */
-    public <T> List<Future<T>> invokeAll(final Collection<? extends Callable<T>> tasks, final long timeout, final TimeUnit unit) throws
-            InterruptedException {
-        return poolExecutor.invokeAll(tasks, timeout, unit);
-    }
-
-    /**
-     * 执行给定的任务
-     * <p>如果某个任务已成功完成(也就是未抛出异常),则返回其结果。
-     * 一旦正常或异常返回后,则取消尚未完成的任务。
-     * 如果此操作正在进行时修改了给定的collection,则此方法的结果是不确定的。</p>
-     *
-     * @param tasks 任务集合
-     * @param <T>   泛型
-     * @return 某个任务返回的结果
-     * @throws InterruptedException 如果等待时发生中断
-     * @throws ExecutionException   如果没有任务成功完成
-     */
-    public <T> T invokeAny(final Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
-        return poolExecutor.invokeAny(tasks);
-    }
-
-    /**
-     * 执行给定的任务
-     * <p>如果在给定的超时期满前某个任务已成功完成(也就是未抛出异常),则返回其结果。
-     * 一旦正常或异常返回后,则取消尚未完成的任务。
-     * 如果此操作正在进行时修改了给定的collection,则此方法的结果是不确定的。</p>
-     *
-     * @param tasks   任务集合
-     * @param timeout 最长等待时间
-     * @param unit    时间单位
-     * @param <T>     泛型
-     * @return 某个任务返回的结果
-     * @throws InterruptedException 如果等待时发生中断
-     * @throws ExecutionException   如果没有任务成功完成
-     * @throws TimeoutException     如果在所有任务成功完成之前给定的超时期满
-     */
-    public <T> T invokeAny(final Collection<? extends Callable<T>> tasks, final long timeout, final TimeUnit unit) throws
-            InterruptedException, ExecutionException, TimeoutException {
-        return poolExecutor.invokeAny(tasks, timeout, unit);
-    }
-
-    /**
-     * 待以前提交的任务执行完毕后关闭线程池
-     * <p>启动一次顺序关闭,执行以前提交的任务,但不接受新任务。
-     * 如果已经关闭,则调用没有作用。</p>
-     */
-    public void shutDown() {
-        poolExecutor.shutdown();
-    }
-
-    /**
-     * 试图停止所有正在执行的活动任务
-     * <p>试图停止所有正在执行的活动任务,暂停处理正在等待的任务,并返回等待执行的任务列表。</p>
-     * <p>无法保证能够停止正在处理的活动执行任务,但是会尽力尝试。</p>
-     *
-     * @return 等待执行的任务的列表
-     */
-    public List<Runnable> shutDownNow() {
-        return poolExecutor.shutdownNow();
-    }
-
-    /**
-     * 判断线程池是否已关闭
-     *
-     * @return {@code true}: 是<br>{@code false}: 否
-     */
-    public boolean isShutDown() {
-        return poolExecutor.isShutdown();
-    }
-
-    /**
-     * 关闭线程池后判断所有任务是否都已完成
-     * <p>注意,除非首先调用 shutdown 或 shutdownNow,否则 isTerminated 永不为 true。</p>
-     *
-     * @return {@code true}: 是<br>{@code false}: 否
-     */
-    public boolean isTerminated() {
-        return poolExecutor.isTerminated();
-    }
-
-    /**
-     * 请求关闭、发生超时或者当前线程中断
-     * <p>无论哪一个首先发生之后,都将导致阻塞,直到所有任务完成执行。</p>
-     *
-     * @param timeout 最长等待时间
-     * @param unit    时间单位
-     * @return {@code true}: 请求成功<br>{@code false}: 请求超时
-     * @throws InterruptedException 终端异常
-     */
-    public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException {
-        return poolExecutor.awaitTermination(timeout, unit);
-    }
-}

+ 18 - 0
compdfkit-tools/src/main/res/drawable/tools_ic_more.xml

@@ -0,0 +1,18 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+  <path
+      android:pathData="M16,28.222c6.75,0 12.222,-5.472 12.222,-12.222s-5.472,-12.222 -12.222,-12.222 -12.222,5.472 -12.222,12.222 5.472,12.222 12.222,12.222zM16,30.222c-7.855,0 -14.222,-6.367 -14.222,-14.222s6.367,-14.222 14.222,-14.222 14.222,6.367 14.222,14.222 -6.367,14.222 -14.222,14.222z"
+      android:fillColor="#000000"/>
+  <path
+      android:pathData="M17.778,16c0,0.982 -0.796,1.778 -1.778,1.778s-1.778,-0.796 -1.778,-1.778c0,-0.982 0.796,-1.778 1.778,-1.778s1.778,0.796 1.778,1.778z"
+      android:fillColor="#000000"/>
+  <path
+      android:pathData="M10.667,16c0,0.982 -0.796,1.778 -1.778,1.778s-1.778,-0.796 -1.778,-1.778c0,-0.982 0.796,-1.778 1.778,-1.778s1.778,0.796 1.778,1.778z"
+      android:fillColor="#000000"/>
+  <path
+      android:pathData="M24.889,16c0,0.982 -0.796,1.778 -1.778,1.778s-1.778,-0.796 -1.778,-1.778c0,-0.982 0.796,-1.778 1.778,-1.778s1.778,0.796 1.778,1.778z"
+      android:fillColor="#000000"/>
+</vector>

Разлика између датотеке није приказан због своје велике величине
+ 9 - 0
compdfkit-tools/src/main/res/drawable/tools_ic_outline.xml


+ 9 - 0
compdfkit-tools/src/main/res/drawable/tools_ic_search.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="32"
+    android:viewportHeight="32">
+  <path
+      android:pathData="M12.889,20.953c4.418,0 8,-3.582 8,-8s-3.582,-8 -8,-8 -8,3.582 -8,8 3.582,8 8,8zM20.447,19.158l7.99,7.99c0.347,0.347 0.347,0.91 0,1.257s-0.91,0.347 -1.257,0l-7.981,-7.981c-1.703,1.44 -3.905,2.308 -6.309,2.308 -5.4,0 -9.778,-4.378 -9.778,-9.778s4.378,-9.778 9.778,-9.778c5.4,0 9.778,4.378 9.778,9.778 0,2.355 -0.833,4.516 -2.22,6.204z"
+      android:fillColor="#000000"/>
+</vector>

+ 58 - 0
compdfkit-tools/src/main/res/layout/tools_cpdf_tool_bar.xml

@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:layout_height="?android:attr/actionBarSize">
+
+
+    <androidx.appcompat.widget.AppCompatTextView
+        android:id="@+id/tv_tool_bar_title"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:textColor="@android:color/black"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        tools:text="PDF View" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_tool_bar_search"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_margin="10dp"
+        android:padding="4dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintEnd_toStartOf="@id/iv_tool_bar_outline"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/tools_ic_search" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_tool_bar_outline"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_margin="10dp"
+        android:padding="4dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintEnd_toStartOf="@id/iv_tool_bar_more"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/tools_ic_outline" />
+
+    <androidx.appcompat.widget.AppCompatImageView
+        android:id="@+id/iv_tool_bar_more"
+        android:layout_width="0dp"
+        android:layout_height="match_parent"
+        android:layout_margin="10dp"
+        android:padding="4dp"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintDimensionRatio="1:1"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:srcCompat="@drawable/tools_ic_more" />
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 9 - 0
compdfkit-tools/src/main/res/values/tools_attrs.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+
+    <declare-styleable name="Tools_CPDFToolBar">
+        <attr name="tools_toolbar_title" format="string"/>
+    </declare-styleable>
+
+</resources>

+ 1 - 1
edit-ctrl-demo/build.gradle

@@ -5,7 +5,7 @@ plugins {
 android {
     namespace 'com.compdfkit.demo.edit'
     compileSdk rootProject.ext.android.COMPILESDK
-    resourcePrefix 'compdfkit_edit_'
+    resourcePrefix 'edit_'
 
     defaultConfig {
         applicationId "com.compdfkit.demo.edit"

+ 1 - 1
form-ctrl-demo/build.gradle

@@ -5,7 +5,7 @@ plugins {
 android {
     namespace 'com.compdfkit.demo.edit'
     compileSdk rootProject.ext.android.COMPILESDK
-    resourcePrefix 'compdfkit_form_'
+    resourcePrefix 'form_'
 
     defaultConfig {
         applicationId "com.compdfkit.demo.edit"

+ 1 - 1
pageedit-ctrl-demo/build.gradle

@@ -5,7 +5,7 @@ plugins {
 android {
     namespace 'com.compdfkit.demo.pageedit'
     compileSdk rootProject.ext.android.COMPILESDK
-    resourcePrefix 'compdfkit_pageedit_'
+    resourcePrefix 'pageedit_'
 
     defaultConfig {
         applicationId "com.compdfkit.demo.pageedit"

+ 2 - 4
viewer-ctrl-demo/build.gradle

@@ -5,10 +5,10 @@ plugins {
 android {
     namespace 'com.compdfkit.demo.viewer'
     compileSdk rootProject.ext.android.COMPILESDK
-    resourcePrefix 'compdfkit_viewer_'
+    resourcePrefix 'viewer_'
 
     defaultConfig {
-        applicationId "com.compdfkit.demo.viewer"
+        applicationId "com.compdfkit.pdfviewer"
         minSdk rootProject.ext.android.MINSDK
         targetSdk rootProject.ext.android.TARGETSDK
         versionCode rootProject.ext.android.VERSIONCODE
@@ -36,7 +36,5 @@ dependencies {
     implementation 'com.google.android.material:material:1.8.0'
     implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
     implementation project(':compdfkit-tools')
-    api 'com.github.bumptech.glide:glide:4.13.2'
-    annotationProcessor 'com.github.bumptech.glide:compiler:4.13.2'
 
 }

+ 2 - 2
viewer-ctrl-demo/src/main/AndroidManifest.xml

@@ -7,9 +7,9 @@
     <application
         android:allowBackup="true"
         android:icon="@mipmap/ic_launcher"
-        android:label="@string/app_name"
+        android:label="@string/viewer_app_name"
         android:supportsRtl="true"
-        android:theme="@style/Theme.Compdfkit_android_demo">
+        android:theme="@style/Viewer_Ctrl_Demo_Theme">
         <activity
             android:name=".MainActivity"
             android:exported="true">

+ 10 - 10
viewer-ctrl-demo/src/main/java/com/compdfkit/demo/viewer/MainActivity.java

@@ -4,26 +4,26 @@ import androidx.appcompat.app.AppCompatActivity;
 
 import android.os.Bundle;
 
-import com.compdfkit.demo.viewer.databinding.CompdfkitViewerActivityMainBinding;
-import com.compdfkit.tools.utils.FileUtilsExtension;
-
-import java.io.File;
+import com.compdfkit.demo.viewer.databinding.ViewerActivityMainBinding;
+import com.compdfkit.tools.task.CExtractAssetFileTask;
 
 public class MainActivity extends AppCompatActivity {
 
+    /**
+     * assets folder pdf file
+     */
     public static final String QUICK_START_GUIDE = "Quick Start Guide V2.4.0.pdf";
 
-
-    private CompdfkitViewerActivityMainBinding binding;
+    private ViewerActivityMainBinding binding;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        binding = CompdfkitViewerActivityMainBinding.inflate(getLayoutInflater());
+        binding = ViewerActivityMainBinding.inflate(getLayoutInflater());
         setContentView(binding.getRoot());
-        File pdfFilePath = new File(this.getCacheDir(), QUICK_START_GUIDE);
-        FileUtilsExtension.copyFileFromAssets(this, QUICK_START_GUIDE, pdfFilePath.getParent(), QUICK_START_GUIDE);
-        binding.pdfReaderView.openPDFFile(pdfFilePath.getAbsolutePath());
+
+        CExtractAssetFileTask.extract(this, QUICK_START_GUIDE, QUICK_START_GUIDE, (pdfFile) ->
+                runOnUiThread(() -> binding.pdfReaderView.openPdfFile(pdfFile.getAbsolutePath())));
 
     }
 

+ 0 - 15
viewer-ctrl-demo/src/main/res/layout/compdfkit_viewer_activity_main.xml

@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:app="http://schemas.android.com/apk/res-auto"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    tools:context=".MainActivity">
-
-    <com.compdfkit.tools.pdfview.PDFReaderView
-        android:id="@+id/pdf_reader_view"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"/>
-
-
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 27 - 0
viewer-ctrl-demo/src/main/res/layout/viewer_activity_main.xml

@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".MainActivity">
+
+    <com.compdfkit.tools.pdfview.CPDFToolBar
+        android:id="@+id/cpdf_tool_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+
+        />
+
+    <com.compdfkit.tools.pdfview.CPDFReaderView
+        android:id="@+id/pdf_reader_view"
+        android:layout_width="match_parent"
+        android:layout_height="0dp"
+        app:layout_constraintTop_toBottomOf="@id/cpdf_tool_bar"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+
+
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 1 - 1
viewer-ctrl-demo/src/main/res/values-night/themes.xml

@@ -1,6 +1,6 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Base application theme. -->
-    <style name="Theme.Compdfkit_android_demo" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+    <style name="Viewer_Ctrl_Demo_Theme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
         <!-- Primary brand color. -->
         <item name="colorPrimary">@color/purple_200</item>
         <item name="colorPrimaryVariant">@color/purple_700</item>

+ 1 - 1
viewer-ctrl-demo/src/main/res/values/strings.xml

@@ -1,3 +1,3 @@
 <resources>
-    <string name="app_name">viewer-ctrl-demo</string>
+    <string name="viewer_app_name">viewer-ctrl-demo</string>
 </resources>

+ 1 - 1
viewer-ctrl-demo/src/main/res/values/themes.xml

@@ -1,6 +1,6 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Base application theme. -->
-    <style name="Theme.Compdfkit_android_demo" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
+    <style name="Viewer_Ctrl_Demo_Theme" parent="Theme.MaterialComponents.DayNight.NoActionBar">
         <!-- Primary brand color. -->
         <item name="colorPrimary">@color/purple_500</item>
         <item name="colorPrimaryVariant">@color/purple_700</item>