Android矢量繪圖應用開發
練習1:超簡單的涂鴉App
準備工作:安裝 ADT Bundle 開發環境(我用的是v23,官方下載被墻,可從這下載)。
-
新建 Android 程序項目。
a. SDK 最小版本選 API 16 以上(避免自動創建的 appcompat_v7 項目出現資源缺失錯誤),完成后可改回低版本(使用 TouchVG 要求最低 API 12)。
b. 在創建 Activity 頁面選擇默認的簡單布局 Blank Activity。
-
在主頁面布局中添加一個 FrameLayout,將用作繪圖區的容器。
a. 指定 ID 為container,下面就可通過findViewById(R.id.container)找到此布局。
b. 使用 FrameLayout 而不是其他布局類型做繪圖視圖容器,是避免觸摸繪圖引起其他相鄰視圖聯鎖刷新。
-
添加 TouchVG 引用。
a. 下載預編譯的TouchVG包,將 touchvg.jar 和 libtouchvg.so 復制到程序項目的 libs 下。
b. 如需調試進入 TouchVG 或快速查看 IViewHelper 接口注釋,則不能復制touchvg.jar,可將 TouchVG項目 復制到上級目錄并導入TouchVG工程,在程序項目的 project.properties 中加入引用:
android.library.reference.1=../TouchVG
-
在 MainActivity.java 中創建繪圖視圖。
a. 定義 IViewHelper 對象,在 onCreate 中創建繪圖視圖。
public class MainActivity extends Activity { private IViewHelper mHelper = ViewFactory.createHelper(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mHelper.createGraphView(this, (ViewGroup) this.findViewById(R.id.container)); mHelper.setCommand("splines"); }
b. 在createGraphView下一行的setCommand激活隨手畫命令。splines是命令名,更多命令名見在線文檔。
c. 將createGraphView換為createSurfaceView可基于 SurfaceView 創建繪圖視圖,適合大量圖形或頁面上有較多控件的情況。在普通 View 上繪圖時占用主線程顯示,刷新時可能引起頁面其他視圖被動刷新。在 SurfaceView 上可異步繪圖,避免連鎖刷新問題。
-
運行程序,動手畫圖吧。
練習2:添加繪圖按鈕
-
添加按鈕布局和按鈕圖片。
在 res/drawable 中添加五個按鈕圖片,在 res/layout 中添加按鈕布局 button_bar.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="fill_parent" android:orientation="vertical" > <ImageButton android:id="@+id/line_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/line" /> <ImageButton android:id="@+id/select_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/select" /> </LinearLayout>
主界面布局 activity_main.xml:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/horzLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <include android:id="@+id/buttons_bar" layout="@layout/buttons_bar" /> <FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent" > </FrameLayout> </LinearLayout>
-
添加按鈕響應,激活相應繪圖命令。
@Override protected void onCreate(Bundle savedInstanceState) { ..... initButtons(); } private void initButtons() { findViewById(R.id.line_btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHelper.setCommand("line"); } }); findViewById(R.id.select_btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHelper.setCommand("select"); } }); }
-
再次運行程序,點按鈕可繪制多種圖形。但選擇圖形出來幾個空的按鈕。
-
添加上下文按鈕資源、本地化串資源。從預編譯的TouchVG包中,將 res/drawable-hdpi、res/drawable-mdpi、res/values 合并到程序中。其中 res/values/strings.xml 不能直接復制文件,需要合并文字內容。
練習3:增加自動保存和恢復功能
目前重啟程序或按Home鍵,返回程序后所繪圖形會丟失。可以增加自動保存和恢復功能。
-
在 AndroidManifest.xml 中增加 MOUNT_UNMOUNT_FILESYSTEMS 和 WRITE_EXTERNAL_STORAGE 權限,以便讀寫外部存儲器。
-
在 MainActivity 中實現 onDestroy、onPause、onSaveInstanceState、onRestoreInstanceState,分別調用 IViewHelper 中相似名稱的函數。在創建繪圖視圖時傳入 savedInstanceState,返回 Activity 時自動恢復圖形:mHelper.createGraphView(this, layout, savedInstanceState);。
練習4:增加線寬動態修改和更新功能
選中一個圖形,可動態(所見即所得)修改其線寬等屬性。沒有選中圖形時設置的圖形屬性將應用到新畫的圖形上。
-
在 Activity 布局中增加一個滑塊控件,ID為lineWidthBar,最大值為 20,即最大20像素寬。
-
在 MainActivity 的 onCreate 中設置滑動響應:
mLineWidthBar = (SeekBar) findViewById(R.id.lineWidthBar); mLineWidthBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mHelper.setStrokeWidth(progress); } @Override public void onStartTrackingTouch(SeekBar seekBar) { mHelper.setContextEditing(true); } @Override public void onStopTrackingTouch(SeekBar seekBar) { mHelper.setContextEditing(false); } });
其中,調用 setContextEditing 是避免在拖動滑塊過程中多次提交改動,產生多次Undo步驟(下面會實現Undo)。
-
為了在選中不同的圖形后更新線寬滑塊值,需要增加選擇改變觀察者:
mHelper.getGraphView().setOnSelectionChangedListener(new OnSelectionChangedListener() { @Override public void onSelectionChanged(IGraphView view) { mLineWidthBar.setProgress(mHelper.getStrokeWidth()); } });
練習5:增加顏色選擇框
-
在工程中導入Android-Color-Picker庫。這里就直接添加源碼(com.chiralcode.colorpicker)了。也可以換為其他顏色選取框項目,例如 HoloColorPicker。
-
增加一個按鈕,點擊時顯示顏色選擇對話框:
findViewById(R.id.colorpicker_btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { new ColorPickerDialog(MainActivity.this, mHelper.getLineColor(), new OnColorSelectedListener() { @Override public void onColorSelected(int color) { mHelper.setLineColor(color); } }).show(); } });
練習6:增加Undo/Redo功能
-
在頁面布局中增加兩個按鈕,ID為 undo_btn 和 redo_btn。
-
在按鈕點擊響應中執行Undo/Redo操作,并準備錄制Undo信息:
findViewById(R.id.undo_btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHelper.undo(); } }); findViewById(R.id.redo_btn).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { mHelper.redo(); } }); mHelper.startUndoRecord(PATH + "undo");
-
增加圖形內容改變的觀察者,在圖形改變時更新按鈕狀態:
mHelper.getGraphView().setOnContentChangedListener(new OnContentChangedListener() { @Override public void onContentChanged(IGraphView view) { findViewById(R.id.undo_btn).setEnabled(mHelper.canUndo()); findViewById(R.id.redo_btn).setEnabled(mHelper.canRedo()); } });
所有源碼已在GitHub開放,歡迎試驗評論。
來自:http://my.oschina.net/rhcad/blog/395596