編輯:關於Android編程
前言
我們知道,在android端顯示文檔內容時,大多都是將文檔轉換為html頁面,然後加載到webview中進行展示。這種展示方法好處在於可以結合html5、css和js做出非常美觀的文檔。但是對於html5、css和js不熟悉的人,可就有點蛋疼了。由於項目的需要,我基於github開源的AndroidTreeView和AndroidPdfViewer兩個控件,通過組合形成了本文的“帶書簽的pdf”控件,通過點擊書簽,能夠展開和收起書簽,同時跳轉到相應頁面,也勉強夠用了。
自定義View簡介
常見的Android自定義View主要有兩種類型:
組合控件:通過組合現有的Android的基礎控件,以達到復用的目的。比如試題控件(TextView+VideoGroup)和本文將要介紹的“帶書簽的PdfView”控件等,這種自定義View的難點在於程序的邏輯處理;MyPdfViewer實戰
本文的開發環境為AndroidStudio2.2.2。先上一張效果圖
1、新建項目:
新建一個Android Phone and Tablet項目,命名為PDFExample。然後添加一個Android Library類庫(Module),在這個庫裡實現我們的帶書簽的PdfViewer控件。
2、添加依賴
在library類庫的build.gradle中添加對AndroidTreeView和AndroidPdfViewer的依賴:
compile 'com.github.barteksc:android-pdf-viewer:2.1.0'
compile 'com.github.bmelnychuk:atv:1.2.+'
3、添加屬性
自定義帶書簽的控件的屬性包括是否顯示書簽、書簽寬度權重和內容寬度權重三個屬性。如下:
<resources>
<declare-styleablename="MyPDFView">
<attrname="bookmark_visiable"format="boolean"/>
<attrname="bookmark_weight"format="dimension"/>
<attrname="content_weight"format="dimension"/>
declare-styleable>
resources>
4、書簽節點Holder的實現
通過AndroidTreeView控件作者的介紹可知,自定義書簽節點時需要繼承TreeNode.BaseNodeViewHolder類,並重寫createNodeView()方法。我們的書簽節點由TextView和兩個ImageView三部分構成,TextView展示書簽的內容,第一個ImageView指示書簽是展開還是收起。
展示書簽內容的代碼在loadComplete()方法中,該方法調用getTree(),通過遞歸展示所有的書簽。
java詳細代碼如下:
package com.***.library; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.widget.ImageView; import android.widget.TextView; import com.github.barteksc.pdfviewer.PDFView; import com.unnamed.b.atv.model.TreeNode; public class BookMarkTreeItemHolder extends TreeNode.BaseNodeViewHolder{ private TextView tvValue; private ImageView arrowView; public BookMarkTreeItemHolder(Context context){ super(context); } @Override public View createNodeView(final TreeNode node, final IconTreeItem value) { final LayoutInflater inflater = LayoutInflater.from(context); final View view = inflater.inflate(R.layout.layout_bookmark_node, null, false); tvValue = (TextView) view.findViewById(R.id.node_value); tvValue.setText(value.text); final ImageView iconView = (ImageView) view.findViewById(R.id.icon); iconView.setImageResource(R.drawable.bookmark); arrowView = (ImageView) view.findViewById(R.id.arrow_icon); if(value.isLeaf){ arrowView.setVisibility(View.INVISIBLE); } return view; } @Override public void toggle(boolean active) { if(mNode.isLeaf()){//如果是葉節點,隱藏展開或收起圖片 arrowView.setVisibility(View.INVISIBLE); } else { arrowView.setVisibility(View.VISIBLE); if(active){ arrowView.setRotation(90); } else { arrowView.setRotation(0); } } } @Override public int getContainerStyle() { return R.style.TreeNodeStyleCustom; } /** * 書簽節點類 */ public static class IconTreeItem { public boolean isLeaf;//是否是葉節點 public long pageIndex; //該節點所在頁面 public String text;//節點內容 public IconTreeItem(boolean isLeaf, long pageIndex, String text) { this.isLeaf = isLeaf; this.pageIndex = pageIndex; this.text = text; } } }
書簽節點布局代碼如下:
5、自定義MyPDFViewer
自定義MyPDFViewer,繼承自LinearLayout,並實現com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener。代碼如下:
package com.***.library;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.LinearLayout;
import com.github.barteksc.pdfviewer.PDFView;
import com.github.barteksc.pdfviewer.listener.OnLoadCompleteListener;
import com.shockwave.pdfium.PdfDocument;
import com.unnamed.b.atv.model.TreeNode;
import com.unnamed.b.atv.view.AndroidTreeView;
import java.io.File;
import java.util.List;
/**
* Created by JKWANG-PC on 2017/1/4.
*/
public class MyPDFViewer extends LinearLayout implements OnLoadCompleteListener {
private LinearLayout bookMarkContainer;//書簽布局
private PDFView pdfView;
private List bookMarks;
private AndroidTreeView treeView;
private boolean bookMarkVisiable = true;
private int bookMarkWeight = 1;//書簽的寬度,為權重值
private int contentWeight = 3;//pdf文檔的寬度,為權重值
private String pdfPath;
private String passWord;
public MyPDFViewer(Context context) {
this(context, null);
}
public MyPDFViewer(Context context, AttributeSet attrs) {
super(context, attrs);
setOrientation(HORIZONTAL);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyPDFViewer);
bookMarkVisiable = typedArray.getBoolean(R.styleable.MyPDFViewer_bookmark_visiable, true);
bookMarkWeight = typedArray.getInteger(R.styleable.MyPDFViewer_bookmark_weight, 1);
contentWeight = typedArray.getInteger(R.styleable.MyPDFViewer_content_weight, 3);
bookMarkContainer = new LinearLayout(getContext());
bookMarkContainer.setOrientation(VERTICAL);
pdfView = new PDFView(getContext(), null);
//在代碼中編寫布局
addView(bookMarkContainer);
addView(pdfView);
}
public void load(){
if(pdfPath.isEmpty() || pdfPath == null){
return;
}
bookMarkContainer.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, bookMarkWeight));
bookMarkContainer.setVisibility(bookMarkVisiable ? VISIBLE : GONE);
pdfView.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, contentWeight));
pdfView.fromFile(new File(pdfPath))
.pages(null) // all pages are displayed by default
.enableSwipe(true)
.swipeHorizontal(false)
.enableDoubletap(true)
.defaultPage(0)
.enableAnnotationRendering(true)
.password(passWord)//pdf打開密碼
.scrollHandle(null)
.onLoad(this)
.load();
pdfView.zoomTo(1.75f);
pdfView.setMaxZoom(1.75f);
pdfView.setMinZoom(1.75f);
}
public boolean isBookMarkVisiable() {
return bookMarkVisiable;
}
public MyPDFViewer setBookMarkVisiable(boolean bookMarkVisiable) {
this.bookMarkVisiable = bookMarkVisiable;
return this;
}
public int getBookMarkWeight() {
return bookMarkWeight;
}
public MyPDFViewer setBookMarkWeight(int bookMarkWeight) {
this.bookMarkWeight = bookMarkWeight;
return this;
}
public int getContentWeight() {
return contentWeight;
}
public MyPDFViewer setContentWeight(int contentWeight) {
this.contentWeight = contentWeight;
return this;
}
public String getPdfPath() {
return pdfPath;
}
public MyPDFViewer setPdfPath(String pdfPath) {
this.pdfPath = pdfPath;
return this;
}
public String getPassWord() {
return passWord;
}
public MyPDFViewer setPassWord(String passWord) {
this.passWord = passWord;
return this;
}
@Override
public void loadComplete(int nbPages) {
Log.e("tag", "load complete");
bookMarks = pdfView.getTableOfContents();
TreeNode root = TreeNode.root();
for (int i = 0, n = bookMarks.size(); i < n; ++i) {
TreeNode parent = new TreeNode(new BookMarkTreeItemHolder.IconTreeItem(bookMarks.get(i).getChildren().size() > 0 ? false : true, bookMarks.get(i).getPageIdx(), bookMarks.get(i).getTitle()))
.setViewHolder(new BookMarkTreeItemHolder(getContext()));
getTree(bookMarks.get(i).getChildren(), parent);//遞歸獲取所有書簽
root.addChild(parent);
}
treeView = new AndroidTreeView(getContext(), root);
treeView.setDefaultAnimation(true);
treeView.setDefaultViewHolder(BookMarkTreeItemHolder.class);
treeView.setDefaultContainerStyle(R.style.TreeNodeStyleCustom);
treeView.setDefaultNodeClickListener(nodeClickListener);//綁定書簽節點點擊事件
bookMarkContainer.addView(treeView.getView());
}
private TreeNode.TreeNodeClickListener nodeClickListener = new TreeNode.TreeNodeClickListener() {
@Override
public void onClick(TreeNode node, Object value) {
BookMarkTreeItemHolder.IconTreeItem item = (BookMarkTreeItemHolder.IconTreeItem) value;
pdfView.jumpTo((int) item.pageIndex);//點擊書簽節點時,跳轉到指定頁面
}
};
//遞歸獲取所有書簽節點
public void getTree(List bookmarks, TreeNode parent) {
for (int i = 0, n = bookmarks.size(); i < n; ++i) {
TreeNode child = new TreeNode(new BookMarkTreeItemHolder.IconTreeItem(bookmarks.get(i).hasChildren() ? false : true, bookmarks.get(i).getPageIdx(), bookmarks.get(i).getTitle()))
.setViewHolder(new BookMarkTreeItemHolder(getContext()));
if (bookmarks.get(i).hasChildren()) {
getTree(bookmarks.get(i).getChildren(), child);
}
parent.addChild(child);
}
}
}
6、MyPDFViewer應用
在app的MainActivity調用自定義的MyPDFViewe控件,代碼如下:
public class MainActivity extends AppCompatActivity {
private MyPDFViewer pdfView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pdfView=(MyPDFViewer)findViewById(R.id.pdfView);
pdfView.setPdfPath(Environment.getExternalStorageDirectory().getPath() + "/Download/瘋狂Android講義 第3版.PDF")
//.setPassWord("1234")
.setBookMarkWeight(2)
.setContentWeight(5)
.load();
Log.e("load:","load complete");
}
}
至此,關於自定義MyPDFViewer組合控件就完成了,非常簡單,但是比較實用。
微信第三方登錄Android實現代碼
記錄一下微信第三方實現登錄的方法。還是比較簡單。一、必要的准備工作1.首先需要注冊並被審核通過的微信開放平台帳號,然後創建一個移動應用,也需要被審核;2.然後到資源中心下
Android事件總線 ( AndroidEventBus ) 框架發布
// ActivityA中注冊廣播接收器 class ActivityA extends Activity { @Override
Android中BaseActivity自定義標題欄
再做一個項目的時候,要求標題欄的標題再中間,樣式,字體大小都要自定義。左邊一個返回按鈕,一個關閉按鈕,右邊定義一個提交按鈕,有時候顯示有時候隱藏。因為原生的title標題
手機百度地圖買汽車票圖文教程
手機都可以買火車票、飛機票了,唯獨買汽車票還是有困難。百度地圖作為出行必備的手機應用,不僅可以查公交,現在還能查詢跨市的長途汽車了,更可以直接在線買票,免去