Browse Source

ComPDFKit Demo(Android) - 1.缩略图列表 2.主题样式统一

liuxiaolong 1 year ago
parent
commit
079995707e
29 changed files with 992 additions and 209 deletions
  1. 16 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/interfaces/OnSetPDFDisplayPageIndexListener.java
  2. 6 7
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/bota/CPDFBotaDialogFragment.java
  3. 38 14
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/bota/adapter/CBotaViewPagerAdapter.java
  4. 3 3
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfoutline/CPDFOutlineFragment.java
  5. 4 5
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfoutline/adapter/COutlineListAdapter.java
  6. 0 24
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfoutline/interfaces/OnOutlineClickListener.java
  7. 10 36
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfthumbnail/CPDFThumbnailFragment.java
  8. 96 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfthumbnail/adpater/CPDFThumbnailListAdapter.java
  9. 0 47
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfthumbnail/adpater/CThumbnailListAdapter.java
  10. 1 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFReaderView.java
  11. 33 12
      compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFToolBar.java
  12. 0 13
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/CPDFAppGlideModule.java
  13. 1 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/dialog/DialogFragmentUtil.java
  14. 197 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/GlideLoadUtil.java
  15. 60 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/MyAppGlideModule.java
  16. 175 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/pdf/GlidePDFUrl.java
  17. 105 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/pdf/TPDFFether.java
  18. 45 0
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/pdf/TPDFGlideUrlLoad.java
  19. 33 10
      compdfkit-tools/src/main/java/com/compdfkit/tools/utils/view/CToolBar.java
  20. 1 3
      compdfkit-tools/src/main/res/layout/tools_cpdf_bota_dialog_fragment.xml
  21. 4 1
      compdfkit-tools/src/main/res/layout/tools_cpdf_tool_bar.xml
  22. 2 1
      compdfkit-tools/src/main/res/layout/tools_ctool_bar.xml
  23. 1 1
      compdfkit-tools/src/main/res/layout/tools_outline_list_item.xml
  24. 5 1
      compdfkit-tools/src/main/res/layout/tools_thumbnail_list_item.xml
  25. 1 2
      viewer-ctrl-demo/src/main/java/com/compdfkit/demo/viewer/MainActivity.java
  26. 1 0
      viewer-ctrl-demo/src/main/res/layout/viewer_activity_main.xml
  27. 26 11
      viewer-ctrl-demo/src/main/res/values-night/themes.xml
  28. 100 7
      viewer-ctrl-demo/src/main/res/values/colors.xml
  29. 28 11
      viewer-ctrl-demo/src/main/res/values/themes.xml

+ 16 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/interfaces/OnSetPDFDisplayPageIndexListener.java

@@ -0,0 +1,16 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ *
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.tools.interfaces;
+
+
+public interface OnSetPDFDisplayPageIndexListener {
+
+    void displayPage(int pageIndex);
+}

+ 6 - 7
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/bota/CPDFBotaDialogFragment.java

@@ -69,26 +69,25 @@ public class CPDFBotaDialogFragment extends BottomSheetDialogFragment {
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-
         initViewPagers();
-
     }
 
     private void initViewPagers(){
-        CBotaViewPagerAdapter botaViewPagerAdapter = new CBotaViewPagerAdapter(this, cpdfReaderView);
-        botaViewPagerAdapter.setOutlineClickListener(pageIndex -> {
+        CBotaViewPagerAdapter boTaViewPagerAdapter = new CBotaViewPagerAdapter(getChildFragmentManager(), getLifecycle(), cpdfReaderView);
+        //Listen to thumbnail and outline click events, CPDFReaderView jumps to the corresponding page and dismisses the popup
+        boTaViewPagerAdapter.setPDFDisplayPageIndexListener(pageIndex -> {
             cpdfReaderView.getCPdfReaderView().setDisplayPageIndex(pageIndex);
             dismiss();
         });
-        viewPager2.setAdapter(botaViewPagerAdapter);
+        viewPager2.setAdapter(boTaViewPagerAdapter);
         viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
             @Override
             public void onPageSelected(int position) {
-                toolBar.setTitle(botaViewPagerAdapter.titles[position]);
+                toolBar.setTitle(boTaViewPagerAdapter.titles[position]);
             }
         });
         TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(tabLayout, viewPager2, (tab, position) -> {
-            tab.setText(botaViewPagerAdapter.titles[position]);
+            tab.setText(boTaViewPagerAdapter.titles[position]);
         });
         tabLayoutMediator.attach();
     }

+ 38 - 14
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/bota/adapter/CBotaViewPagerAdapter.java

@@ -12,30 +12,43 @@ package com.compdfkit.tools.pdfbota.bota.adapter;
 
 import androidx.annotation.NonNull;
 import androidx.fragment.app.Fragment;
+import androidx.fragment.app.FragmentManager;
+import androidx.lifecycle.Lifecycle;
 import androidx.viewpager2.adapter.FragmentStateAdapter;
 
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.pdfbota.pdfoutline.CPDFOutlineFragment;
-import com.compdfkit.tools.pdfbota.pdfoutline.interfaces.OnOutlineClickListener;
+import com.compdfkit.tools.interfaces.OnSetPDFDisplayPageIndexListener;
+import com.compdfkit.tools.pdfbota.pdfthumbnail.CPDFThumbnailFragment;
 import com.compdfkit.tools.pdfview.CPDFReaderView;
 
 public class CBotaViewPagerAdapter extends FragmentStateAdapter {
-
+    /**
+     * Array of titles for the two fragments
+     */
     public int[] titles = new int[]{R.string.tools_thumbnail, R.string.tools_outline};
+
+    /**
+     * The PDF reader view object
+     */
     private CPDFReaderView cpdfReaderView;
 
-    private OnOutlineClickListener outlineCallback;
+    /**
+     * Listener for setting the display page index of the PDF
+     */
+    private OnSetPDFDisplayPageIndexListener pdfDisplayPageIndexListener;
 
-    public CBotaViewPagerAdapter(@NonNull Fragment fragment, CPDFReaderView cpdfReaderView) {
-        super(fragment);
+    public CBotaViewPagerAdapter(@NonNull FragmentManager fragmentManager, @NonNull Lifecycle lifecycle, CPDFReaderView cpdfReaderView) {
+        super(fragmentManager, lifecycle);
         this.cpdfReaderView = cpdfReaderView;
     }
 
+
     @NonNull
     @Override
     public Fragment createFragment(int position) {
         if (position == 0){
-            return outlineFragment();
+            return thumbnailFragment();
         }else {
             return outlineFragment();
         }
@@ -43,25 +56,36 @@ public class CBotaViewPagerAdapter extends FragmentStateAdapter {
 
     @Override
     public int getItemCount() {
-        return 2;
+        return titles.length;
     }
 
+    /**
+     * Method that creates and returns a new outline fragment
+     * @return CPDFOutlineFragment
+     */
     private CPDFOutlineFragment outlineFragment(){
         CPDFOutlineFragment fragment = CPDFOutlineFragment.newInstance();
-        fragment.setOutlineClickListener(outlineCallback);
+        fragment.setOutlineClickListener(pdfDisplayPageIndexListener);
         fragment.setCPdfReaderView(cpdfReaderView);
         return fragment;
     }
 
-    private CPDFOutlineFragment thumbnailFragment(){
-        CPDFOutlineFragment fragment = CPDFOutlineFragment.newInstance();
-        fragment.setOutlineClickListener(outlineCallback);
+    /**
+     * Method that creates and returns a new thumbnail fragment
+     * @return CPDFThumbnailFragment
+     */
+    private CPDFThumbnailFragment thumbnailFragment(){
+        CPDFThumbnailFragment fragment = CPDFThumbnailFragment.newInstance();
+        fragment.setPDFDisplayPageIndexListener(pdfDisplayPageIndexListener);
         fragment.setCPdfReaderView(cpdfReaderView);
         return fragment;
     }
 
-
-    public void setOutlineClickListener(OnOutlineClickListener outlineClickListener){
-        this.outlineCallback = outlineClickListener;
+    /**
+     * Method that sets the PDF display page index listener
+     * @param displayPageIndexListener
+     */
+    public void setPDFDisplayPageIndexListener(OnSetPDFDisplayPageIndexListener displayPageIndexListener){
+        this.pdfDisplayPageIndexListener = displayPageIndexListener;
     }
 }

+ 3 - 3
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfoutline/CPDFOutlineFragment.java

@@ -25,7 +25,7 @@ import com.compdfkit.tools.R;
 import com.compdfkit.tools.pdfbota.pdfoutline.adapter.COutlineListAdapter;
 import com.compdfkit.tools.pdfbota.pdfoutline.bean.COutlineData;
 import com.compdfkit.tools.pdfbota.pdfoutline.data.COutlineDatas;
-import com.compdfkit.tools.pdfbota.pdfoutline.interfaces.OnOutlineClickListener;
+import com.compdfkit.tools.interfaces.OnSetPDFDisplayPageIndexListener;
 import com.compdfkit.tools.pdfview.CPDFReaderView;
 
 import java.util.ArrayList;
@@ -34,7 +34,7 @@ public class CPDFOutlineFragment extends Fragment {
 
     private RecyclerView rvOutlineRecyclerView;
 
-    private OnOutlineClickListener outlineCallback;
+    private OnSetPDFDisplayPageIndexListener outlineCallback;
 
     private CPDFReaderView cpdfReaderView;
 
@@ -94,7 +94,7 @@ public class CPDFOutlineFragment extends Fragment {
      *
      * @param outlineClickListener The listener to set.
      */
-    public void setOutlineClickListener(OnOutlineClickListener outlineClickListener) {
+    public void setOutlineClickListener(OnSetPDFDisplayPageIndexListener outlineClickListener) {
         this.outlineCallback = outlineClickListener;
     }
 

+ 4 - 5
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfoutline/adapter/COutlineListAdapter.java

@@ -20,10 +20,9 @@ import androidx.recyclerview.widget.RecyclerView;
 
 import com.compdfkit.tools.R;
 import com.compdfkit.tools.pdfbota.pdfoutline.bean.COutlineData;
-import com.compdfkit.tools.pdfbota.pdfoutline.interfaces.OnOutlineClickListener;
+import com.compdfkit.tools.interfaces.OnSetPDFDisplayPageIndexListener;
 
 import java.util.ArrayList;
-import java.util.Iterator;
 import java.util.List;
 
 
@@ -33,7 +32,7 @@ public class COutlineListAdapter extends RecyclerView.Adapter<COutlineListAdapte
 
     private List<COutlineData> list = new ArrayList<>();
 
-    private OnOutlineClickListener outlineClickListener;
+    private OnSetPDFDisplayPageIndexListener outlineClickListener;
 
     /**
      * set outline list data
@@ -70,7 +69,7 @@ public class COutlineListAdapter extends RecyclerView.Adapter<COutlineListAdapte
         holder.itemView.setOnClickListener(v -> {
             if (item.childOutlineIsEmpty()) {
                 if (outlineClickListener != null) {
-                    outlineClickListener.callback(item.getPageIndex());
+                    outlineClickListener.displayPage(item.getPageIndex());
                 }
             } else {
                 if (item.isExpand()) {
@@ -166,7 +165,7 @@ public class COutlineListAdapter extends RecyclerView.Adapter<COutlineListAdapte
         }
     }
 
-    public void setOutlineClickListener(OnOutlineClickListener outlineClickListener) {
+    public void setOutlineClickListener(OnSetPDFDisplayPageIndexListener outlineClickListener) {
         this.outlineClickListener = outlineClickListener;
     }
 

+ 0 - 24
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfoutline/interfaces/OnOutlineClickListener.java

@@ -1,24 +0,0 @@
-/**
- * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
- *
- * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
- * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
- * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
- * This notice may not be removed from this file.
- */
-
-package com.compdfkit.tools.pdfbota.pdfoutline.interfaces;
-
-
-/**
- * This interface is used by COutlineListAdapter to return the page index when an item in the RecyclerView is clicked.
- * @see com.compdfkit.tools.pdfbota.pdfoutline.adapter.COutlineListAdapter#setOutlineClickListener(OnOutlineClickListener)
- */
-public interface OnOutlineClickListener{
-
-    /**
-     * This callback is used to return the page index of the PDF document linked to an outline item when it is clicked.
-     * @param pageIndex the page index of the PDF document linked to the clicked outline item.
-     */
-    void callback(int pageIndex);
-}

+ 10 - 36
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfthumbnail/CPDFThumbnailFragment.java

@@ -18,23 +18,19 @@ import android.view.ViewGroup;
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 import androidx.fragment.app.Fragment;
-import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.GridLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
 import com.compdfkit.tools.R;
-import com.compdfkit.tools.pdfbota.pdfoutline.adapter.COutlineListAdapter;
-import com.compdfkit.tools.pdfbota.pdfoutline.bean.COutlineData;
-import com.compdfkit.tools.pdfbota.pdfoutline.data.COutlineDatas;
-import com.compdfkit.tools.pdfbota.pdfoutline.interfaces.OnOutlineClickListener;
+import com.compdfkit.tools.interfaces.OnSetPDFDisplayPageIndexListener;
+import com.compdfkit.tools.pdfbota.pdfthumbnail.adpater.CPDFThumbnailListAdapter;
 import com.compdfkit.tools.pdfview.CPDFReaderView;
 
-import java.util.ArrayList;
-
 public class CPDFThumbnailFragment extends Fragment {
 
     private RecyclerView rvThumbnailRecyclerView;
 
-    private OnOutlineClickListener outlineCallback;
+    private OnSetPDFDisplayPageIndexListener displayPageIndexListener;
 
     private CPDFReaderView cpdfReaderView;
 
@@ -67,35 +63,13 @@ public class CPDFThumbnailFragment extends Fragment {
 
     @Override
     public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
-        // Set up the adapter and the RecyclerView.
-        COutlineListAdapter outlineListAdapter = new COutlineListAdapter();
-        outlineListAdapter.setOutlineClickListener(outlineCallback);
-        rvThumbnailRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
-        rvThumbnailRecyclerView.setAdapter(outlineListAdapter);
-        // Set the list of outline data for the adapter to display.
-        outlineListAdapter.setList(getOutlineData());
-    }
-
-    /**
-     * Returns the list of outline data for the PDF document.
-     *
-     * @return The list of outline data.
-     */
-    private ArrayList<COutlineData> getOutlineData() {
-        if (cpdfReaderView != null) {
-            return COutlineDatas.getOutlineList(cpdfReaderView);
-        } else {
-            return new ArrayList<>();
-        }
+        CPDFThumbnailListAdapter thumbnailListAdapter = new CPDFThumbnailListAdapter(cpdfReaderView.getCPdfReaderView().getPDFDocument());
+        thumbnailListAdapter.setPDFDisplayPageIndexListener(displayPageIndexListener);
+        rvThumbnailRecyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));
+        rvThumbnailRecyclerView.setAdapter(thumbnailListAdapter);
     }
 
-    /**
-     * Sets the listener for outline item click events.
-     *
-     * @param outlineClickListener The listener to set.
-     */
-    public void setOutlineClickListener(OnOutlineClickListener outlineClickListener) {
-        this.outlineCallback = outlineClickListener;
+    public void setPDFDisplayPageIndexListener(OnSetPDFDisplayPageIndexListener displayPageIndexListener) {
+        this.displayPageIndexListener = displayPageIndexListener;
     }
-
 }

+ 96 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfthumbnail/adpater/CPDFThumbnailListAdapter.java

@@ -0,0 +1,96 @@
+/**
+ * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
+ * <p>
+ * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
+ * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
+ * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
+ * This notice may not be removed from this file.
+ */
+
+package com.compdfkit.tools.pdfbota.pdfthumbnail.adpater;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.appcompat.widget.AppCompatImageView;
+import androidx.appcompat.widget.AppCompatTextView;
+import androidx.cardview.widget.CardView;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.compdfkit.core.document.CPDFDocument;
+import com.compdfkit.tools.R;
+import com.compdfkit.tools.interfaces.OnSetPDFDisplayPageIndexListener;
+import com.compdfkit.tools.utils.glide.GlideLoadUtil;
+import com.compdfkit.tools.utils.glide.pdf.GlidePDFUrl;
+
+public class CPDFThumbnailListAdapter extends RecyclerView.Adapter<CPDFThumbnailListAdapter.CPDFThumbnailItemViewHolder> {
+
+    private CPDFDocument cPdfDocument;
+
+    private OnSetPDFDisplayPageIndexListener displayPageIndexListener;
+
+    public CPDFThumbnailListAdapter(CPDFDocument cDdfDocument) {
+        this.cPdfDocument = cDdfDocument;
+    }
+
+
+    @NonNull
+    @Override
+    public CPDFThumbnailItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+        return new CPDFThumbnailItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.tools_thumbnail_list_item, parent, false));
+    }
+
+    @Override
+    public void onBindViewHolder(@NonNull CPDFThumbnailItemViewHolder holder, int position) {
+        int[] size = getPdfImageSize(holder.ivThumbnailImage);
+        GlideLoadUtil.loadPDFPageImage(holder.itemView.getContext(),
+                new GlidePDFUrl(cPdfDocument, position, size[0], size[1]),
+                cPdfDocument.getAbsolutePath(),
+                false,
+                false,
+                holder.ivThumbnailImage
+        );
+        holder.tvPageIndex.setText(String.valueOf(holder.getAdapterPosition() + 1));
+        holder.cardView.setOnClickListener(v -> {
+            if (displayPageIndexListener != null) {
+                displayPageIndexListener.displayPage(holder.getAdapterPosition());
+            }
+        });
+    }
+
+    private int[] getPdfImageSize(AppCompatImageView imageView){
+        int[] size = new int[]{300, 300};
+        int width = imageView.getWidth();
+        int height = imageView.getHeight();
+        if (width > 0 && height > 0){
+            size[0] = width;
+            size[1] = height;
+        }
+        return size;
+    }
+
+    @Override
+    public int getItemCount() {
+        return cPdfDocument.getPageCount();
+    }
+
+    public void setPDFDisplayPageIndexListener(OnSetPDFDisplayPageIndexListener listener) {
+        this.displayPageIndexListener = listener;
+    }
+
+    static class CPDFThumbnailItemViewHolder extends RecyclerView.ViewHolder {
+        private AppCompatImageView ivThumbnailImage;
+        private AppCompatTextView tvPageIndex;
+
+        private CardView cardView;
+
+        public CPDFThumbnailItemViewHolder(@NonNull View itemView) {
+            super(itemView);
+            ivThumbnailImage = itemView.findViewById(R.id.iv_thumbnail);
+            tvPageIndex = itemView.findViewById(R.id.tv_thumbnail_page_index);
+            cardView = itemView.findViewById(R.id.card_view);
+        }
+    }
+}

+ 0 - 47
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfbota/pdfthumbnail/adpater/CThumbnailListAdapter.java

@@ -1,47 +0,0 @@
-/**
- * Copyright © 2014-2023 PDF Technologies, Inc. All Rights Reserved.
- *
- * THIS SOURCE CODE AND ANY ACCOMPANYING DOCUMENTATION ARE PROTECTED BY INTERNATIONAL COPYRIGHT LAW
- * AND MAY NOT BE RESOLD OR REDISTRIBUTED. USAGE IS BOUND TO THE ComPDFKit LICENSE AGREEMENT.
- * UNAUTHORIZED REPRODUCTION OR DISTRIBUTION IS SUBJECT TO CIVIL AND CRIMINAL PENALTIES.
- * This notice may not be removed from this file.
- */
-
-package com.compdfkit.tools.pdfbota.pdfthumbnail.adpater;
-
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-
-import androidx.annotation.NonNull;
-import androidx.recyclerview.widget.RecyclerView;
-
-import com.compdfkit.tools.R;
-
-public class CThumbnailListAdapter extends RecyclerView.Adapter<CThumbnailListAdapter.CPDFThumbnailItemViewHolder>{
-
-
-
-    @NonNull
-    @Override
-    public CPDFThumbnailItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
-        return new CPDFThumbnailItemViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.tools_thumbnail_list_item, parent, false));
-    }
-
-    @Override
-    public void onBindViewHolder(@NonNull CPDFThumbnailItemViewHolder holder, int position) {
-
-    }
-
-    @Override
-    public int getItemCount() {
-        return 0;
-    }
-
-    static class CPDFThumbnailItemViewHolder extends RecyclerView.ViewHolder{
-
-        public CPDFThumbnailItemViewHolder(@NonNull View itemView) {
-            super(itemView);
-        }
-    }
-}

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

@@ -40,6 +40,7 @@ public class CPDFReaderView extends FrameLayout {
 
     private void initCPDFReaderView() {
         cPdfReaderView = new com.compdfkit.ui.reader.CPDFReaderView(getContext());
+        cPdfReaderView.setDoublePageMode(false);
         addView(cPdfReaderView);
     }
 

+ 33 - 12
compdfkit-tools/src/main/java/com/compdfkit/tools/pdfview/CPDFToolBar.java

@@ -11,11 +11,14 @@ package com.compdfkit.tools.pdfview;
 
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
@@ -25,8 +28,10 @@ import androidx.annotation.Nullable;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.appcompat.widget.AppCompatImageView;
 import androidx.appcompat.widget.AppCompatTextView;
+import androidx.core.view.ViewCompat;
 
 import com.compdfkit.tools.R;
+import com.google.android.material.shape.MaterialShapeDrawable;
 
 public class CPDFToolBar extends FrameLayout {
 
@@ -36,23 +41,23 @@ public class CPDFToolBar extends FrameLayout {
     private AppCompatImageView ivToolBarMoreBtn;
 
     public CPDFToolBar(@NonNull Context context) {
-        super(context);
-        initToolBar(context, null);
+        this(context, null);
     }
 
     public CPDFToolBar(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        initToolBar(context, attrs);
+        this(context, attrs, 0);
     }
 
     public CPDFToolBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+
+
+        initToolBar(context, attrs);
+
     }
 
     private void initToolBar(Context context, @Nullable AttributeSet attrs) {
         LayoutInflater.from(getContext()).inflate(R.layout.tools_cpdf_tool_bar, this);
-        setBackgroundColor(Color.WHITE);
-        setElevation(8);
         tvToolBarTitle = findViewById(R.id.tv_tool_bar_title);
         ivToolBarMoreBtn = findViewById(R.id.iv_tool_bar_more);
         ivToolBarSearchBtn = findViewById(R.id.iv_tool_bar_search);
@@ -80,33 +85,49 @@ public class CPDFToolBar extends FrameLayout {
             if (moreIconDrawable != null) {
                 ivToolBarMoreBtn.setImageDrawable(moreIconDrawable);
             }
+
+            int color;
+            if (getBackground() != null && getBackground() instanceof ColorDrawable) {
+                ColorDrawable colorDrawable = (ColorDrawable) getBackground();
+                color = colorDrawable.getColor();
+            } else {
+                TypedValue typedValue = new TypedValue();
+                getContext().getTheme().resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true);
+                color = typedValue.data;
+            }
+            MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
+            materialShapeDrawable.setFillColor(ColorStateList.valueOf(color));
+            materialShapeDrawable.initializeElevationOverlay(context);
+            materialShapeDrawable.setElevation(ViewCompat.getElevation(this));
+            ViewCompat.setBackground(this, materialShapeDrawable);
+
             typedArray.recycle();
         }
     }
 
-    private Drawable loadImageFromAttributes(TypedArray typedArray, int index, int defValue){
+    private Drawable loadImageFromAttributes(TypedArray typedArray, int index, int defValue) {
         Drawable drawable = null;
         try {
             int resId = typedArray.getResourceId(index, defValue);
-            if (resId != -1){
+            if (resId != -1) {
                 drawable = AppCompatResources.getDrawable(getContext(), resId);
             }
             return drawable;
-        }catch (Exception e){
+        } catch (Exception e) {
             return null;
         }
     }
 
 
-    public void setSearchBtnClickListener(View.OnClickListener clickListener){
+    public void setSearchBtnClickListener(View.OnClickListener clickListener) {
         ivToolBarSearchBtn.setOnClickListener(clickListener);
     }
 
-    public void setOutlineBtnClickListener(View.OnClickListener clickListener){
+    public void setOutlineBtnClickListener(View.OnClickListener clickListener) {
         ivToolBarOutlineBtn.setOnClickListener(clickListener);
     }
 
-    public void setMoreBtnClickListener(View.OnClickListener clickListener){
+    public void setMoreBtnClickListener(View.OnClickListener clickListener) {
         ivToolBarMoreBtn.setOnClickListener(clickListener);
     }
 

+ 0 - 13
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/CPDFAppGlideModule.java

@@ -1,13 +0,0 @@
-package com.compdfkit.tools.utils;
-
-import com.bumptech.glide.annotation.GlideModule;
-import com.bumptech.glide.module.AppGlideModule;
-
-
-@GlideModule
-public class CPDFAppGlideModule extends AppGlideModule {
-    @Override
-    public boolean isManifestParsingEnabled() {
-        return false;
-    }
-}

+ 1 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/dialog/DialogFragmentUtil.java

@@ -25,6 +25,7 @@ public class DialogFragmentUtil {
 
     public static void setBottomSheetDialogFragmentFullScreen(@Nullable Dialog dialog, BottomSheetBehavior<View> behavior) {
         behavior.setState(BottomSheetBehavior.STATE_EXPANDED);
+        behavior.setSkipCollapsed(true);
         if (dialog == null) {
             return;
         }

+ 197 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/GlideLoadUtil.java

@@ -0,0 +1,197 @@
+package com.compdfkit.tools.utils.glide;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.widget.ImageView;
+
+import androidx.annotation.Nullable;
+import androidx.fragment.app.Fragment;
+
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.DecodeFormat;
+import com.bumptech.glide.load.engine.DiskCacheStrategy;
+import com.bumptech.glide.load.engine.GlideException;
+import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions;
+import com.bumptech.glide.request.RequestListener;
+import com.bumptech.glide.request.target.Target;
+import com.bumptech.glide.signature.ObjectKey;
+import com.compdfkit.tools.utils.glide.pdf.GlidePDFUrl;
+import com.compdfkit.tools.utils.threadpools.CThreadPoolUtils;
+
+/**
+ * Glide图片加载工具类;有其他需求后期添加
+ */
+public class GlideLoadUtil {
+
+    /**
+     * @param :[c, url, target]
+     * @return : void
+     * @description :加载图片不需要缓存的
+     */
+    public static void loadSourceImgWithNoCache(Context c, String url, ImageView target) {
+        GlideApp.with(c)
+                .load(url)
+                .diskCacheStrategy(DiskCacheStrategy.NONE)
+                .skipMemoryCache(true)
+                .centerCrop()
+                .transition(new DrawableTransitionOptions().crossFade(200))
+                .into(target);
+    }
+
+    public static void LoadGiftAsGistKeepFidelity(Context context, int url, ImageView imageView, int erroId) {
+        GlideApp.with(context)
+                .asGif()
+                .load(url)
+                .format(DecodeFormat.PREFER_ARGB_8888)
+                .error(erroId)
+                .into(imageView);
+    }
+
+    /**
+     * @param :[c, resourceId, target, defaultId]
+     * @return : void
+     * @description :根据资源ID加载图片
+     */
+    public static void loadResourseImg(Context c, int resourceId, ImageView target, int defaultId) {
+        GlideApp.with(c)
+                .load(resourceId)
+                .placeholder(defaultId)
+                .transition(new DrawableTransitionOptions().crossFade(200))
+                .centerCrop()
+                .into(target);
+    }
+
+    /**
+     * @param :[c, imgFile, target, defaultId]
+     * @return : void
+     * @description :根据图片路径加载图片
+     */
+    public static void loadStampImg(Context c, String imgFilePath, ImageView target, int width, int height) {
+        GlideApp.with(c)
+                .load(imgFilePath)
+                .transition(new DrawableTransitionOptions().crossFade(200))
+                .centerCrop()
+                .skipMemoryCache(true)
+                .override(width, height)
+                .diskCacheStrategy(DiskCacheStrategy.RESOURCE)
+                .into(target);
+    }
+
+    public static void loadPDFPageImage(Context c, GlidePDFUrl glidePDFUrl, String filePath, boolean diskCacheStrategy, boolean memoryCache, Target target) {
+        GlideApp.with(c)
+                .asBitmap()
+                .load(glidePDFUrl)
+                .signature(new ObjectKey(String.format("%s_%s_%s", filePath, glidePDFUrl.getPageIndex(), System.currentTimeMillis() - 10000)))
+                .diskCacheStrategy(diskCacheStrategy ? DiskCacheStrategy.DATA : DiskCacheStrategy.NONE)
+                .skipMemoryCache(!memoryCache)
+                .into(target);
+    }
+
+    public static void loadPDFPageImage(Context c, GlidePDFUrl glidePDFUrl, String filePath, boolean diskCacheStrategy, boolean memoryCache, ImageView imageView) {
+        GlideApp.with(c)
+                .asBitmap()
+                .load(glidePDFUrl)
+                .signature(new ObjectKey(String.format("%s_%s_%s", filePath, glidePDFUrl.getPageIndex(), System.currentTimeMillis() - 10000)))
+                .diskCacheStrategy(diskCacheStrategy ? DiskCacheStrategy.DATA : DiskCacheStrategy.NONE)
+                .skipMemoryCache(!memoryCache)
+                .into(imageView);
+    }
+
+    /**
+     * @param :[context, url, imageView]
+     * @return : void
+     * @description :加载Gif为一张静态图片
+     */
+    public static void LoadGiftAsBitmap(Context context, String url, ImageView imageView) {
+        GlideApp.with(context).asBitmap().load(url).into(imageView);
+    }
+
+    /**
+     * @param :[context, url, imageView, erroId]
+     * @return : void
+     * @description :你想只有加载对象是Gif时才能加载成功
+     */
+    public static void LoadGiftAsGist(Context context, String url, ImageView imageView, int erroId) {
+        GlideApp.with(context).asGif().load(url).error(erroId).into(imageView);
+    }
+
+    /**
+     * @param :[fragment, url, imageView]
+     * @return : void
+     * @description :加载缩略图,会自动与传入的fragment绑定生命周期,加载请求现在会自动在onStop中暂停在,onStart中重新开始。
+     * 需要保证 ScaleType 的设置是正确的。
+     */
+    public static void LoadThumbNail(Fragment fragment, String url, ImageView imageView) {
+        GlideApp.with(fragment).load(url).thumbnail(0.1f).into(imageView);
+    }
+
+    /**
+     * @param :[context, url, target, placeholder_resId, error_resId]
+     * @return : void
+     * @description :加载圆形头像;如果是activity glide会与其生命周期关联,在onStop()中取消加载图片,如果
+     * 想要始终加载图片则需要传入Application实例
+     */
+    public static void loadRoundImg(Context context, String url, ImageView target, int placeholder_resId, int error_resId) {
+        //https://github.com/wasabeef/glide-transformations--glide转换库
+        GlideApp.with(context)
+                .load(url)
+                .placeholder(placeholder_resId)
+                .error(error_resId)
+                .circleCrop()//直接在链式中调用就行哦
+                .transition(new DrawableTransitionOptions().crossFade(1000))//渐显效果
+                .into(target);
+    }
+
+    /**
+     * @param :[context, url]
+     * @return : android.graphics.Bitmap
+     * @description :下载图片,耗时操作不能放在主线程中进行
+     */
+    public static Bitmap downLoadImage(Context context, String url) {
+        try {
+            return GlideApp.with(context).asBitmap().load(url).centerCrop().listener(new RequestListener<Bitmap>() {
+                @Override
+                public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
+                    return false;
+                }
+
+                @Override
+                public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
+                    return false;
+                }
+            }).submit().get();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return null;
+    }
+
+    /**
+     * @param :[context]
+     * @return : void
+     * @description :清除缓存
+     */
+    public static void clearCache(final Context context) {
+        clearMemoryCache(context);
+        CThreadPoolUtils.getInstance().execute(() -> clearDiskCache(context));
+    }
+
+    /**
+     * @param :[context]
+     * @return : void
+     * @description :清除内存缓存
+     */
+    public static void clearMemoryCache(Context context) {
+        GlideApp.get(context).clearMemory();
+    }
+
+    /**
+     * @param :[context]
+     * @return : void
+     * @description :清除磁盘缓存
+     */
+    public static void clearDiskCache(Context context) {
+        GlideApp.get(context).clearDiskCache();
+    }
+}

+ 60 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/MyAppGlideModule.java

@@ -0,0 +1,60 @@
+package com.compdfkit.tools.utils.glide;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.GlideBuilder;
+import com.bumptech.glide.Registry;
+import com.bumptech.glide.annotation.GlideModule;
+import com.bumptech.glide.load.DecodeFormat;
+import com.bumptech.glide.load.engine.bitmap_recycle.LruBitmapPool;
+import com.bumptech.glide.load.engine.cache.InternalCacheDiskCacheFactory;
+import com.bumptech.glide.load.engine.cache.LruResourceCache;
+import com.bumptech.glide.load.engine.cache.MemorySizeCalculator;
+import com.bumptech.glide.module.AppGlideModule;
+import com.bumptech.glide.request.RequestOptions;
+import com.compdfkit.tools.utils.glide.pdf.GlidePDFUrl;
+import com.compdfkit.tools.utils.glide.pdf.TPDFGlideUrlLoad;
+
+@GlideModule
+public class MyAppGlideModule extends AppGlideModule {
+
+    @Override
+    public void applyOptions(@NonNull Context context, @NonNull GlideBuilder builder) {
+        /*内存缓存池*/
+        MemorySizeCalculator cache_calculator = new MemorySizeCalculator.Builder(context)
+                .setMemoryCacheScreens(2)
+                .build();
+        builder.setMemoryCache(new LruResourceCache(cache_calculator.getMemoryCacheSize()));
+
+        /*磁盘缓存*/
+        //100 MB
+        int diskCacheSizeBytes = 1024 * 1024 * 100;
+        builder.setDiskCache(new InternalCacheDiskCacheFactory(context, diskCacheSizeBytes));
+
+        /*Bitmap 池*/
+        MemorySizeCalculator bitmap_calculator = new MemorySizeCalculator.Builder(context)
+                .setBitmapPoolScreens(3)
+                .build();
+        builder.setBitmapPool(new LruBitmapPool(bitmap_calculator.getBitmapPoolSize()));
+
+        builder.setDefaultRequestOptions(
+                new RequestOptions()
+                        .format(DecodeFormat.PREFER_RGB_565)
+                        .disallowHardwareConfig());
+    }
+
+    @Override
+    public boolean isManifestParsingEnabled() {
+        return false;
+    }
+
+    @Override
+    public void registerComponents(@NonNull Context context, @NonNull Glide glide, @NonNull Registry registry) {
+        registry.append(GlidePDFUrl.class, Bitmap.class, new TPDFGlideUrlLoad.Factory());
+        super.registerComponents(context, glide, registry);
+    }
+}

+ 175 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/pdf/GlidePDFUrl.java

@@ -0,0 +1,175 @@
+package com.compdfkit.tools.utils.glide.pdf;
+
+import android.graphics.Color;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.bumptech.glide.load.Key;
+import com.bumptech.glide.load.model.Headers;
+import com.compdfkit.core.document.CPDFDocument;
+
+import java.security.MessageDigest;
+import java.util.Locale;
+
+
+public class GlidePDFUrl implements Key {
+    private static final String TAG = "GlidePDFUrl";
+    public static final String TPDF = "TPDF:";
+    public static final String TAG_PAGEINDEX = "pageIndex";
+    public static final String TAG_WIDTH = "width";
+    public static final String TAG_HEIGHT = "height";
+    public static final String TAG_PATCHX = "patchx";
+    public static final String TAG_PATCHY = "patchy";
+    public static final String TAG_PATCHW = "patchw";
+    public static final String TAG_PATCHH = "patchh";
+    public static final String TAG_BGCOLOR = "bgcolor";
+    public static final String TAG_DRAWANNOT = "drawannot";
+    public static final String TAG_IS_UPDATE = "isupdate";
+
+    private CPDFDocument tpdfDocument;
+    private int pageIndex;
+    private int width;
+    private int height;
+    private int patchX;
+    private int patchY;
+    private int patchW;
+    private int patchH;
+    private int bgColor;
+    private boolean isDrawAnnot;
+    private boolean isUpdate;
+
+    private final Headers headers = Headers.DEFAULT;
+    private int hashCode;
+    @Nullable
+    private volatile byte[] cacheKeyBytes;
+
+    public GlidePDFUrl(CPDFDocument tpdfDocument, int pageIndex, int width, int height, int patchX, int patchY, int patchW, int patchH, int bgColor, boolean isDrawAnnot, boolean isUpdate) {
+        this.tpdfDocument = tpdfDocument;
+        this.pageIndex = pageIndex;
+        this.width = width;
+        this.height = height;
+        this.patchX = patchX;
+        this.patchY = patchY;
+        this.patchW = patchW;
+        this.patchH = patchH;
+        this.bgColor = bgColor;
+        this.isDrawAnnot = isDrawAnnot;
+        this.isUpdate = isUpdate;
+    }
+
+    public GlidePDFUrl(CPDFDocument tpdfDocument, int pageIndex, int width, int height){
+        this.tpdfDocument = tpdfDocument;
+        this.pageIndex = pageIndex;
+        this.width = width;
+        this.height = height;
+        this.patchX = 0;
+        this.patchY = 0;
+        this.patchW = width;
+        this.patchH = height;
+        this.bgColor = Color.WHITE;
+        this.isDrawAnnot = true;
+        this.isUpdate = false;
+    }
+
+    public CPDFDocument getTpdfDocument() {
+        return tpdfDocument;
+    }
+
+    public int getPageIndex() {
+        return pageIndex;
+    }
+
+    public int getWidth() {
+        return width;
+    }
+
+    public int getHeight() {
+        return height;
+    }
+
+    public int getPatchX() {
+        return patchX;
+    }
+
+    public int getPatchY() {
+        return patchY;
+    }
+
+    public int getPatchW() {
+        return patchW;
+    }
+
+    public int getPatchH() {
+        return patchH;
+    }
+
+    public int getBgColor() {
+        return bgColor;
+    }
+
+    public boolean isDrawAnnot() {
+        return isDrawAnnot;
+    }
+
+    public boolean isUpdate() {
+        return isUpdate;
+    }
+
+    public String getCacheKey() {
+        String urlFormat = "%s{" +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"," +
+                "\"%s\":\"%d\"}";
+        String cacheKey = String.format(Locale.US, urlFormat,
+                TPDF,
+                TAG_PAGEINDEX, pageIndex,
+                TAG_WIDTH, width,
+                TAG_HEIGHT, height,
+                TAG_PATCHX, patchX,
+                TAG_PATCHY, patchY,
+                TAG_PATCHW, patchW,
+                TAG_PATCHH, patchH,
+                TAG_BGCOLOR, bgColor,
+                TAG_DRAWANNOT, (isDrawAnnot ? 1 : 0),
+                TAG_IS_UPDATE, (isUpdate ? 1 : 0));
+        return cacheKey;
+    }
+
+    @Override
+    public void updateDiskCacheKey(@NonNull MessageDigest messageDigest) {
+        messageDigest.update(getCacheKeyBytes());
+    }
+
+    private byte[] getCacheKeyBytes() {
+        if (cacheKeyBytes == null) {
+            cacheKeyBytes = getCacheKey().getBytes(CHARSET);
+        }
+        return cacheKeyBytes;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof GlidePDFUrl) {
+            GlidePDFUrl other = (GlidePDFUrl) o;
+            return getCacheKey().equals(other.getCacheKey());
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = getCacheKey().hashCode();
+            hashCode = 31 * hashCode + headers.hashCode();
+        }
+        return hashCode;
+    }
+}

+ 105 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/pdf/TPDFFether.java

@@ -0,0 +1,105 @@
+package com.compdfkit.tools.utils.glide.pdf;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+
+import androidx.annotation.NonNull;
+
+import com.bumptech.glide.Glide;
+import com.bumptech.glide.Priority;
+import com.bumptech.glide.load.DataSource;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.compdfkit.core.document.CPDFDocument;
+
+public class TPDFFether implements DataFetcher<Bitmap> {
+    private static final int MAXIMUM_REDIRECTS = 1;
+
+    private final static String TAG = "TPDFFether";
+    private GlidePDFUrl glideUrl;
+    private volatile boolean isCancelled;
+    private CPDFDocument tpdfDocument;
+    private Context context;
+
+    public TPDFFether(GlidePDFUrl glideUrl) {
+        this.glideUrl = glideUrl;
+        tpdfDocument = glideUrl.getTpdfDocument();
+        context = tpdfDocument.getContext();
+    }
+
+    @Override
+    public void loadData(@NonNull Priority priority, @NonNull DataCallback<? super Bitmap> callback) {
+//        long startTime = LogTime.getLogTime();
+        try {
+            isCancelled = false;
+            Bitmap result = loadDataWithRedirects(glideUrl.getPageIndex(),
+                    glideUrl.getWidth(),
+                    glideUrl.getHeight(),
+                    glideUrl.getPatchX(),
+                    glideUrl.getPatchY(),
+                    glideUrl.getPatchW(),
+                    glideUrl.getPatchH(),
+                    glideUrl.getBgColor(),
+                    glideUrl.isDrawAnnot(),
+                    glideUrl.isUpdate(),
+                    0);
+            callback.onDataReady(result);
+        } catch (Exception e) {
+            callback.onLoadFailed(e);
+        } finally {
+//            Log.d(TAG, "Finished http url fetcher fetch in " + LogTime.getElapsedMillis(startTime));
+        }
+    }
+
+    private Bitmap loadDataWithRedirects(int pageIndex, int width, int height, int patchX, int patchY, int patchW, int patchH, int bgColor, boolean isDrawAnnot, boolean isUpdate, int redirects) throws Exception {
+        if (redirects >= MAXIMUM_REDIRECTS) {
+            throw new Exception("Too many (> " + MAXIMUM_REDIRECTS + ") redirects!");
+        }
+
+        if (tpdfDocument == null) {
+            throw new Exception("CPDFDocument is null!");
+        }
+        Bitmap bitmap = Glide.get(context).getBitmapPool().get(width, height, Bitmap.Config.ARGB_4444);
+        boolean res = tpdfDocument.renderPageAtIndex(bitmap,
+                pageIndex,
+                width,
+                height,
+                patchX,
+                patchY,
+                patchW,
+                patchH,
+                bgColor,
+                255,
+                0,
+                true,
+                true);
+
+        if (!res || (null == bitmap) || bitmap.isRecycled()) {
+            return loadDataWithRedirects(pageIndex, width, height, patchX, patchY, patchW, patchH, bgColor, isDrawAnnot, isUpdate, ++redirects);
+        }
+//        Log.e(TAG, "loadDataWithRedirects, index:" + glideUrl.getPageIndex() + ", bitmap:" + bitmap.toString());
+        return isCancelled ? null : bitmap;
+    }
+
+    @Override
+    public void cleanup() {
+        glideUrl = null;
+        tpdfDocument = null;
+    }
+
+    @NonNull
+    @Override
+    public Class<Bitmap> getDataClass() {
+        return Bitmap.class;
+    }
+
+    @NonNull
+    @Override
+    public DataSource getDataSource() {
+        return DataSource.REMOTE;
+    }
+
+    @Override
+    public void cancel() {
+        isCancelled = true;
+    }
+}

+ 45 - 0
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/glide/pdf/TPDFGlideUrlLoad.java

@@ -0,0 +1,45 @@
+package com.compdfkit.tools.utils.glide.pdf;
+
+import android.graphics.Bitmap;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.bumptech.glide.load.Options;
+import com.bumptech.glide.load.data.DataFetcher;
+import com.bumptech.glide.load.model.ModelLoader;
+import com.bumptech.glide.load.model.ModelLoaderFactory;
+import com.bumptech.glide.load.model.MultiModelLoaderFactory;
+
+public class TPDFGlideUrlLoad implements ModelLoader<GlidePDFUrl, Bitmap> {
+    public TPDFGlideUrlLoad() {
+    }
+
+    @Nullable
+    @Override
+    public LoadData<Bitmap> buildLoadData(@NonNull GlidePDFUrl model, int width, int height, @NonNull Options options) {
+        DataFetcher dataFetcher = new TPDFFether(model);
+        return new LoadData<>(model, dataFetcher);
+    }
+
+    @Override
+    public boolean handles(@NonNull GlidePDFUrl glideUrl) {
+        return true;
+    }
+
+    public static class Factory implements ModelLoaderFactory<GlidePDFUrl, Bitmap> {
+        public Factory() {
+        }
+
+        @NonNull
+        @Override
+        public ModelLoader<GlidePDFUrl, Bitmap> build(MultiModelLoaderFactory multiFactory) {
+            return new TPDFGlideUrlLoad();
+        }
+
+        @Override
+        public void teardown() {
+            // Do nothing.
+        }
+    }
+}

+ 33 - 10
compdfkit-tools/src/main/java/com/compdfkit/tools/utils/view/CToolBar.java

@@ -11,11 +11,14 @@ package com.compdfkit.tools.utils.view;
 
 
 import android.content.Context;
+import android.content.res.ColorStateList;
 import android.content.res.TypedArray;
 import android.graphics.Color;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.TypedValue;
 import android.view.LayoutInflater;
 import android.widget.FrameLayout;
 
@@ -25,8 +28,11 @@ import androidx.annotation.StringRes;
 import androidx.appcompat.content.res.AppCompatResources;
 import androidx.appcompat.widget.AppCompatImageView;
 import androidx.appcompat.widget.AppCompatTextView;
+import androidx.core.content.ContextCompat;
+import androidx.core.view.ViewCompat;
 
 import com.compdfkit.tools.R;
+import com.google.android.material.shape.MaterialShapeDrawable;
 
 public class CToolBar extends FrameLayout {
 
@@ -34,20 +40,21 @@ public class CToolBar extends FrameLayout {
     private AppCompatImageView ivToolBarBackBtn;
 
     public CToolBar(@NonNull Context context) {
-        super(context);
-        initToolBar(context, null);
+        this(context, null);
     }
 
     public CToolBar(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        initToolBar(context, attrs);
+        this(context, attrs, 0);
     }
 
     public CToolBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
+        initToolBar(context, attrs);
     }
 
+
     private void initToolBar(Context context, @Nullable AttributeSet attrs) {
+
         LayoutInflater.from(getContext()).inflate(R.layout.tools_ctool_bar, this);
         tvToolBarTitle = findViewById(R.id.tv_tool_bar_title);
         ivToolBarBackBtn = findViewById(R.id.iv_tool_bar_back);
@@ -65,33 +72,49 @@ public class CToolBar extends FrameLayout {
             if (backIconDrawable != null) {
                 ivToolBarBackBtn.setImageDrawable(backIconDrawable);
             }
+
+            int color;
+            if (getBackground() != null && getBackground() instanceof ColorDrawable) {
+                ColorDrawable colorDrawable = (ColorDrawable) getBackground();
+                color = colorDrawable.getColor();
+            } else {
+                TypedValue typedValue = new TypedValue();
+                getContext().getTheme().resolveAttribute(com.google.android.material.R.attr.colorSurface, typedValue, true);
+                color = typedValue.data;
+            }
+            MaterialShapeDrawable materialShapeDrawable = new MaterialShapeDrawable();
+            materialShapeDrawable.setFillColor(ColorStateList.valueOf(color));
+            materialShapeDrawable.initializeElevationOverlay(context);
+            materialShapeDrawable.setElevation(ViewCompat.getElevation(this));
+            ViewCompat.setBackground(this, materialShapeDrawable);
+
             typedArray.recycle();
         }
     }
 
-    private Drawable loadImageFromAttributes(TypedArray typedArray, int index, int defValue){
+    private Drawable loadImageFromAttributes(TypedArray typedArray, int index, int defValue) {
         Drawable drawable = null;
         try {
             int resId = typedArray.getResourceId(index, defValue);
-            if (resId != -1){
+            if (resId != -1) {
                 drawable = AppCompatResources.getDrawable(getContext(), resId);
             }
             return drawable;
-        }catch (Exception e){
+        } catch (Exception e) {
             return null;
         }
     }
 
 
-    public void setBackBtnClickListener(OnClickListener clickListener){
+    public void setBackBtnClickListener(OnClickListener clickListener) {
         ivToolBarBackBtn.setOnClickListener(clickListener);
     }
 
-    public void setTitle(@StringRes int titleResId){
+    public void setTitle(@StringRes int titleResId) {
         tvToolBarTitle.setText(titleResId);
     }
 
-    public void setTitle(String title){
+    public void setTitle(String title) {
         tvToolBarTitle.setText(title);
     }
 

+ 1 - 3
compdfkit-tools/src/main/res/layout/tools_cpdf_bota_dialog_fragment.xml

@@ -4,15 +4,13 @@
     android:layout_height="match_parent"
     xmlns:app="http://schemas.android.com/apk/res-auto">
 
-
     <com.compdfkit.tools.utils.view.CToolBar
         android:id="@+id/tool_bar"
         android:layout_width="match_parent"
         android:layout_height="?android:attr/actionBarSize"
         app:tools_toolbar_title="Outline"
-        app:layout_constraintTop_toTopOf="parent"
         android:elevation="4dp"
-        android:background="@color/tools_tool_bar_background_color"
+        app:layout_constraintTop_toTopOf="parent"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"/>
 

+ 4 - 1
compdfkit-tools/src/main/res/layout/tools_cpdf_tool_bar.xml

@@ -11,10 +11,10 @@
         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"
+        android:textColor="?android:attr/textColorPrimary"
         app:layout_constraintTop_toTopOf="parent"
         android:textSize="16sp"
         tools:text="PDF View" />
@@ -25,6 +25,7 @@
         android:layout_height="match_parent"
         android:layout_margin="10dp"
         android:padding="4dp"
+        app:tint="?android:attr/colorAccent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintEnd_toStartOf="@id/iv_tool_bar_outline"
@@ -37,6 +38,7 @@
         android:layout_height="match_parent"
         android:layout_margin="10dp"
         android:padding="4dp"
+        app:tint="?android:attr/colorAccent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintEnd_toStartOf="@id/iv_tool_bar_more"
@@ -49,6 +51,7 @@
         android:layout_height="match_parent"
         android:layout_margin="10dp"
         android:padding="4dp"
+        app:tint="?android:attr/colorAccent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintEnd_toEndOf="parent"

+ 2 - 1
compdfkit-tools/src/main/res/layout/tools_ctool_bar.xml

@@ -11,12 +11,12 @@
         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"
         android:textSize="16sp"
+        android:textColor="?android:attr/textColorPrimary"
         tools:text="PDF View" />
 
     <androidx.appcompat.widget.AppCompatImageView
@@ -25,6 +25,7 @@
         android:layout_height="match_parent"
         android:layout_margin="10dp"
         android:padding="4dp"
+        app:tint="?android:attr/colorAccent"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintDimensionRatio="1:1"
         app:layout_constraintStart_toStartOf="parent"

+ 1 - 1
compdfkit-tools/src/main/res/layout/tools_outline_list_item.xml

@@ -20,6 +20,7 @@
         android:layout_height="match_parent"
         android:visibility="invisible"
         tools:visibility="visible"
+        app:tint="?android:attr/textColorPrimary"
         app:srcCompat="@drawable/tools_ic_right"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@+id/tv_outline_item_padding"
@@ -36,7 +37,6 @@
         android:paddingTop="12dp"
         android:paddingBottom="12dp"
         android:singleLine="true"
-        android:textColor="@android:color/black"
         android:textSize="14sp"
         app:layout_constraintBottom_toBottomOf="parent"
         app:layout_constraintStart_toEndOf="@+id/iv_outline_item_arrow"

+ 5 - 1
compdfkit-tools/src/main/res/layout/tools_thumbnail_list_item.xml

@@ -2,14 +2,17 @@
 <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="wrap_content"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:layout_margin="4dp"
     >
 
     <androidx.cardview.widget.CardView
+        android:id="@+id/card_view"
         android:layout_width="match_parent"
         android:layout_height="0dp"
         app:cardElevation="0dp"
+        android:foreground="?android:attr/selectableItemBackground"
         app:cardUseCompatPadding="true"
         app:cardBackgroundColor="@android:color/white"
         app:layout_constraintBottom_toBottomOf="parent"
@@ -30,6 +33,7 @@
                 tools:src="@tools:sample/avatars"/>
 
             <androidx.appcompat.widget.AppCompatTextView
+                android:id="@+id/tv_thumbnail_page_index"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 tools:text="1"

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

@@ -27,7 +27,6 @@ public class MainActivity extends AppCompatActivity {
         CExtractAssetFileTask.extract(this, QUICK_START_GUIDE, QUICK_START_GUIDE, (pdfFile) ->
                 runOnUiThread(() -> binding.pdfReaderView.openPdfFile(pdfFile.getAbsolutePath())));
 
-
     }
 
 
@@ -39,7 +38,7 @@ public class MainActivity extends AppCompatActivity {
 
             CPDFBotaDialogFragment botaDialogFragment = CPDFBotaDialogFragment.newInstance();
             botaDialogFragment.setCPdfReaderView(binding.pdfReaderView);
-            botaDialogFragment.show(getSupportFragmentManager(), "botaDialogFragment");
+            botaDialogFragment.show(getSupportFragmentManager(), "boTaDialogFragment");
         });
         binding.pdfToolBar.setMoreBtnClickListener(v -> {
 

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

@@ -12,6 +12,7 @@
         android:layout_width="match_parent"
         android:layout_height="?android:attr/actionBarSize"
         app:layout_constraintTop_toTopOf="parent"
+        android:elevation="4dp"
         app:layout_constraintStart_toStartOf="parent"
         app:layout_constraintEnd_toEndOf="parent"
         app:tools_toolbar_title="@string/viewer_toolbar_title"

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

@@ -1,16 +1,31 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Base application theme. -->
     <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>
-        <item name="colorOnPrimary">@color/black</item>
-        <!-- Secondary brand color. -->
-        <item name="colorSecondary">@color/teal_200</item>
-        <item name="colorSecondaryVariant">@color/teal_200</item>
-        <item name="colorOnSecondary">@color/black</item>
-        <!-- Status bar color. -->
-        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
-        <!-- Customize your theme here. -->
+        <item name="colorPrimary">@color/md_theme_dark_primary</item>
+        <item name="colorOnPrimary">@color/md_theme_dark_onPrimary</item>
+        <item name="colorPrimaryContainer">@color/md_theme_dark_primaryContainer</item>
+        <item name="colorOnPrimaryContainer">@color/md_theme_dark_onPrimaryContainer</item>
+        <item name="colorSecondary">@color/md_theme_dark_secondary</item>
+        <item name="colorOnSecondary">@color/md_theme_dark_onSecondary</item>
+        <item name="colorSecondaryContainer">@color/md_theme_dark_secondaryContainer</item>
+        <item name="colorOnSecondaryContainer">@color/md_theme_dark_onSecondaryContainer</item>
+        <item name="colorTertiary">@color/md_theme_dark_tertiary</item>
+        <item name="colorOnTertiary">@color/md_theme_dark_onTertiary</item>
+        <item name="colorTertiaryContainer">@color/md_theme_dark_tertiaryContainer</item>
+        <item name="colorOnTertiaryContainer">@color/md_theme_dark_onTertiaryContainer</item>
+        <item name="colorError">@color/md_theme_dark_error</item>
+        <item name="colorErrorContainer">@color/md_theme_dark_errorContainer</item>
+        <item name="colorOnError">@color/md_theme_dark_onError</item>
+        <item name="colorOnErrorContainer">@color/md_theme_dark_onErrorContainer</item>
+        <item name="android:colorBackground">@color/md_theme_dark_background</item>
+        <item name="colorOnBackground">@color/md_theme_dark_onBackground</item>
+        <item name="colorOutline">@color/md_theme_dark_outline</item>
+        <item name="colorOnSurfaceInverse">@color/md_theme_dark_inverseOnSurface</item>
+        <item name="colorSurfaceInverse">@color/md_theme_dark_inverseSurface</item>
+        <item name="colorSurface">@color/md_theme_dark_surface</item>
+        <item name="colorOnSurface">@color/md_theme_dark_onSurface</item>
+        <item name="colorSurfaceVariant">@color/md_theme_dark_surfaceVariant</item>
+        <item name="colorOnSurfaceVariant">@color/md_theme_dark_onSurfaceVariant</item>
+        <item name="colorPrimaryInverse">@color/md_theme_dark_inversePrimary</item>
     </style>
 </resources>

+ 100 - 7
viewer-ctrl-demo/src/main/res/values/colors.xml

@@ -1,10 +1,103 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    <color name="purple_200">#FFBB86FC</color>
-    <color name="purple_500">#FF6200EE</color>
-    <color name="purple_700">#FF3700B3</color>
-    <color name="teal_200">#FF03DAC5</color>
-    <color name="teal_700">#FF018786</color>
-    <color name="black">#FF000000</color>
-    <color name="white">#FFFFFFFF</color>
+
+    <color name="viewer_seed">#00A89B</color>
+    <color name="md_theme_light_primary">#006A62</color>
+    <color name="md_theme_light_onPrimary">#FFFFFF</color>
+    <color name="md_theme_light_primaryContainer">#73F8E8</color>
+    <color name="md_theme_light_onPrimaryContainer">#00201D</color>
+    <color name="md_theme_light_primaryFixed">#73F8E8</color>
+    <color name="md_theme_light_onPrimaryFixed">#00201D</color>
+    <color name="md_theme_light_primaryFixedDim">#52DBCC</color>
+    <color name="md_theme_light_onPrimaryFixedVariant">#005049</color>
+    <color name="md_theme_light_secondary">#4A635F</color>
+    <color name="md_theme_light_onSecondary">#FFFFFF</color>
+    <color name="md_theme_light_secondaryContainer">#CCE8E3</color>
+    <color name="md_theme_light_onSecondaryContainer">#051F1D</color>
+    <color name="md_theme_light_secondaryFixed">#CCE8E3</color>
+    <color name="md_theme_light_onSecondaryFixed">#051F1D</color>
+    <color name="md_theme_light_secondaryFixedDim">#B1CCC7</color>
+    <color name="md_theme_light_onSecondaryFixedVariant">#324B48</color>
+    <color name="md_theme_light_tertiary">#46617A</color>
+    <color name="md_theme_light_onTertiary">#FFFFFF</color>
+    <color name="md_theme_light_tertiaryContainer">#CDE5FF</color>
+    <color name="md_theme_light_onTertiaryContainer">#001D32</color>
+    <color name="md_theme_light_tertiaryFixed">#CDE5FF</color>
+    <color name="md_theme_light_onTertiaryFixed">#001D32</color>
+    <color name="md_theme_light_tertiaryFixedDim">#AEC9E6</color>
+    <color name="md_theme_light_onTertiaryFixedVariant">#2E4961</color>
+    <color name="md_theme_light_error">#BA1A1A</color>
+    <color name="md_theme_light_errorContainer">#FFDAD6</color>
+    <color name="md_theme_light_onError">#FFFFFF</color>
+    <color name="md_theme_light_onErrorContainer">#410002</color>
+    <color name="md_theme_light_background">#FAFDFB</color>
+    <color name="md_theme_light_onBackground">#191C1C</color>
+    <color name="md_theme_light_outline">#6F7977</color>
+    <color name="md_theme_light_inverseOnSurface">#EFF1EF</color>
+    <color name="md_theme_light_inverseSurface">#2D3130</color>
+    <color name="md_theme_light_inversePrimary">#52DBCC</color>
+    <color name="md_theme_light_shadow">#000000</color>
+    <color name="md_theme_light_surfaceTint">#006A62</color>
+    <color name="md_theme_light_outlineVariant">#BEC9C6</color>
+    <color name="md_theme_light_scrim">#000000</color>
+    <color name="md_theme_light_surface">#F7FAF8</color>
+    <color name="md_theme_light_onSurface">#191C1C</color>
+    <color name="md_theme_light_surfaceVariant">#DAE5E2</color>
+    <color name="md_theme_light_onSurfaceVariant">#3F4947</color>
+    <color name="md_theme_light_surfaceContainerHighest">#E0E3E1</color>
+    <color name="md_theme_light_surfaceContainerHigh">#E6E9E7</color>
+    <color name="md_theme_light_surfaceContainer">#ECEEED</color>
+    <color name="md_theme_light_surfaceContainerLow">#F2F4F2</color>
+    <color name="md_theme_light_surfaceContainerLowest">#FFFFFF</color>
+    <color name="md_theme_light_surfaceDim">#D8DBD9</color>
+    <color name="md_theme_light_surfaceBright">#F7FAF8</color>
+    <color name="md_theme_dark_primary">#52DBCC</color>
+    <color name="md_theme_dark_onPrimary">#003732</color>
+    <color name="md_theme_dark_primaryContainer">#005049</color>
+    <color name="md_theme_dark_onPrimaryContainer">#73F8E8</color>
+    <color name="md_theme_dark_primaryFixed">#73F8E8</color>
+    <color name="md_theme_dark_onPrimaryFixed">#00201D</color>
+    <color name="md_theme_dark_primaryFixedDim">#52DBCC</color>
+    <color name="md_theme_dark_onPrimaryFixedVariant">#005049</color>
+    <color name="md_theme_dark_secondary">#B1CCC7</color>
+    <color name="md_theme_dark_onSecondary">#1C3531</color>
+    <color name="md_theme_dark_secondaryContainer">#324B48</color>
+    <color name="md_theme_dark_onSecondaryContainer">#CCE8E3</color>
+    <color name="md_theme_dark_secondaryFixed">#CCE8E3</color>
+    <color name="md_theme_dark_onSecondaryFixed">#051F1D</color>
+    <color name="md_theme_dark_secondaryFixedDim">#B1CCC7</color>
+    <color name="md_theme_dark_onSecondaryFixedVariant">#324B48</color>
+    <color name="md_theme_dark_tertiary">#AEC9E6</color>
+    <color name="md_theme_dark_onTertiary">#163349</color>
+    <color name="md_theme_dark_tertiaryContainer">#2E4961</color>
+    <color name="md_theme_dark_onTertiaryContainer">#CDE5FF</color>
+    <color name="md_theme_dark_tertiaryFixed">#CDE5FF</color>
+    <color name="md_theme_dark_onTertiaryFixed">#001D32</color>
+    <color name="md_theme_dark_tertiaryFixedDim">#AEC9E6</color>
+    <color name="md_theme_dark_onTertiaryFixedVariant">#2E4961</color>
+    <color name="md_theme_dark_error">#FFB4AB</color>
+    <color name="md_theme_dark_errorContainer">#93000A</color>
+    <color name="md_theme_dark_onError">#690005</color>
+    <color name="md_theme_dark_onErrorContainer">#FFDAD6</color>
+    <color name="md_theme_dark_background">#191C1C</color>
+    <color name="md_theme_dark_onBackground">#E0E3E1</color>
+    <color name="md_theme_dark_outline">#899390</color>
+    <color name="md_theme_dark_inverseOnSurface">#191C1C</color>
+    <color name="md_theme_dark_inverseSurface">#E0E3E1</color>
+    <color name="md_theme_dark_inversePrimary">#006A62</color>
+    <color name="md_theme_dark_shadow">#000000</color>
+    <color name="md_theme_dark_surfaceTint">#52DBCC</color>
+    <color name="md_theme_dark_outlineVariant">#3F4947</color>
+    <color name="md_theme_dark_scrim">#000000</color>
+    <color name="md_theme_dark_surface">#101413</color>
+    <color name="md_theme_dark_onSurface">#C4C7C5</color>
+    <color name="md_theme_dark_surfaceVariant">#3F4947</color>
+    <color name="md_theme_dark_onSurfaceVariant">#BEC9C6</color>
+    <color name="md_theme_dark_surfaceContainerHighest">#323535</color>
+    <color name="md_theme_dark_surfaceContainerHigh">#272B2A</color>
+    <color name="md_theme_dark_surfaceContainer">#1D2020</color>
+    <color name="md_theme_dark_surfaceContainerLow">#191C1C</color>
+    <color name="md_theme_dark_surfaceContainerLowest">#0B0F0E</color>
+    <color name="md_theme_dark_surfaceDim">#101413</color>
+    <color name="md_theme_dark_surfaceBright">#363A39</color>
 </resources>

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

@@ -1,16 +1,33 @@
 <resources xmlns:tools="http://schemas.android.com/tools">
     <!-- Base application theme. -->
     <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>
-        <item name="colorOnPrimary">@color/white</item>
-        <!-- Secondary brand color. -->
-        <item name="colorSecondary">@color/teal_200</item>
-        <item name="colorSecondaryVariant">@color/teal_700</item>
-        <item name="colorOnSecondary">@color/black</item>
-        <!-- Status bar color. -->
-        <item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
-        <!-- Customize your theme here. -->
+
+        <item name="colorPrimary">@color/md_theme_light_primary</item>
+        <item name="colorOnPrimary">@color/md_theme_light_onPrimary</item>
+        <item name="colorPrimaryContainer">@color/md_theme_light_primaryContainer</item>
+        <item name="colorOnPrimaryContainer">@color/md_theme_light_onPrimaryContainer</item>
+        <item name="colorSecondary">@color/md_theme_light_secondary</item>
+        <item name="colorOnSecondary">@color/md_theme_light_onSecondary</item>
+        <item name="colorSecondaryContainer">@color/md_theme_light_secondaryContainer</item>
+        <item name="colorOnSecondaryContainer">@color/md_theme_light_onSecondaryContainer</item>
+        <item name="colorTertiary">@color/md_theme_light_tertiary</item>
+        <item name="colorOnTertiary">@color/md_theme_light_onTertiary</item>
+        <item name="colorTertiaryContainer">@color/md_theme_light_tertiaryContainer</item>
+        <item name="colorOnTertiaryContainer">@color/md_theme_light_onTertiaryContainer</item>
+        <item name="colorError">@color/md_theme_light_error</item>
+        <item name="colorErrorContainer">@color/md_theme_light_errorContainer</item>
+        <item name="colorOnError">@color/md_theme_light_onError</item>
+        <item name="colorOnErrorContainer">@color/md_theme_light_onErrorContainer</item>
+        <item name="android:colorBackground">@color/md_theme_light_background</item>
+        <item name="colorOnBackground">@color/md_theme_light_onBackground</item>
+        <item name="colorOutline">@color/md_theme_light_outline</item>
+        <item name="colorOnSurfaceInverse">@color/md_theme_light_inverseOnSurface</item>
+        <item name="colorSurfaceInverse">@color/md_theme_light_inverseSurface</item>
+        <item name="colorSurface">@color/md_theme_light_surface</item>
+        <item name="colorOnSurface">@color/md_theme_light_onSurface</item>
+        <item name="colorSurfaceVariant">@color/md_theme_light_surfaceVariant</item>
+        <item name="colorOnSurfaceVariant">@color/md_theme_light_onSurfaceVariant</item>
+        <item name="colorPrimaryInverse">@color/md_theme_light_inversePrimary</item>
+        <item name="android:statusBarColor">@color/md_theme_light_primary</item>
     </style>
 </resources>