編輯:關於Android編程
這套框架終於到了完結篇了,這篇就算是整個框架的重點了,涉及的不僅是重做和撤銷功能,更重要的是牽扯整個框架的架構。
之前我們實現的功能是添加圖片和用畫筆繪畫,我們的做法是在一個自定義的PaintLayout上添加一個類似於自定義畫布那樣的去盛放畫筆畫出來的東西,再在PaintLayout上添加圖片,這樣做的不好之處在於各個類之間的功能不明確,現在把項目重新架構成把圖片全部集成到另外一個自定義的ViewLayout上,把ViewLayout加載到PaintLayout上,再放上盛放畫筆畫出的View,也就是TopLayer,在PaintLayout上用兩個鏈表去實現重做和撤銷操作。
我們先看一下ViewLayout的實現。
這裡的ViewLayout其實就是把第一節的PaintLayout稍微改改,但是在這裡得通知外層修改鏈表,所有還得定義個接口,這裡就直接貼代碼了
public class ViewLayout extends FrameLayout{ public interface ViewListener{ void addView(PaintView paintView); void deleteView(PaintView paintView); } private Context context; private LayoutParams params; private ViewListener viewListener; private boolean canInit=false; public ViewLayout(Context context,ViewListener viewListener) { super(context); this.context=context; this.viewListener=viewListener; params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); } private void addView(MotionEvent event){ PaintView paintView=new PaintView(context, (int) event.getX(), (int) event.getY(), new PaintView.OnEnableListener() { @Override public void callback(PaintView stampView) { for (int i = 0; i < ViewLayout.this.getChildCount(); ++i) { if (ViewLayout.this.getChildAt(i) != stampView) { ((PaintView) ViewLayout.this.getChildAt(i)).setViewEnable(false); } } } @Override public void onDelete(PaintView stampView) { stampView.setVisibility(GONE); viewListener.deleteView(stampView); } }); this.addView(paintView,params); viewListener.addView(paintView); } @Override public boolean onTouchEvent(MotionEvent event) { if(canInit&&event.getAction()==MotionEvent.ACTION_DOWN){ addView(event); canInit=false; } return super.onTouchEvent(event); } public void setCanInit(boolean canInit) { this.canInit = canInit; } public void deleteView(PaintView paintView){ ViewLayout.this.removeView(paintView); } public void allStop(){ for (int i = 0; i < ViewLayout.this.getChildCount(); ++i) { ((PaintView) ViewLayout.this.getChildAt(i)).setViewEnable(false); } } }
再去修改TopLayer裡的代碼,我們需要把每次一次從手指觸摸到屏幕到手指抬起之間畫出來的Path保存起來,同樣的,我們在接口中把這個path傳到上層的PaintLayout,而這個Path在撤銷和重做的時候是通過一個boolean值去判斷是否顯示,所以自定義一個ViPath類
public class ViPath { private Path path; private boolean visible; public ViPath(){ visible=true; path=new Path(); } public void moveTo(float x,float y){ path.moveTo(x,y); } public void lineTo(float x,float y){ path.lineTo(x,y); } public Path getPath() { return path; } public void setPath(Path path) { this.path = path; } public boolean isVisible() { return visible; } public void setVisible(boolean visible) { this.visible = visible; } }
public interface PathListener{ void addPath(ViPath viPath); } private ViPath currentPath; private PathListener pathListener; private void touch_end(float eventX, float eventY){ touchPath.lineTo(eventX, eventY); currentPath.lineTo(eventX,eventY); } @Override public boolean onTouchEvent(MotionEvent event) { if (enable) { float eventX = event.getX(); float eventY = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: touch_start(eventX, eventY); currentPath=new ViPath(); currentPath.moveTo(eventX,eventY); touchPoints = 0; break; case MotionEvent.ACTION_MOVE: touchPoints++; if ((touchPoints % 3) == 0){ touch_end(eventX, eventY); start_paint(touchPath, paint); touch_start(eventX, eventY); } break; case MotionEvent.ACTION_UP: touch_end(eventX, eventY); start_paint(touchPath, paint); pathListener.addPath(currentPath); break; default: break; } invalidate(); return true; } else { return false; } }
在這裡還得寫一個函數供外層調用,就是當重做和撤銷的時候,重繪整個TopLayer
public void drawPath(List
現在TopLayer和ViewLayout都有了,我們需要做的就是在主布局中去調用,這裡的做法是定義兩個盛放Object的鏈表saveOperate和restoreOperate,當做撤銷操作的時候,將saveOperate的尾節點放到restoreOperate裡面,並根據它是不同的類型進行響應,當做重做操作的時候,把saveOperate的尾節點放到restoreOperate裡面,而一旦進行新的操作,比如添加圖片或者繪圖之類的,將restoreOperate鏈表清空,並釋放相關資源
public class PaintLayout extends FrameLayout{ private TopLayer topLayer; private ViewLayout viewLayout; private LayoutParams params; private List
寫在前面從事Android開發至今,一提及Android開發中使用的對話框就想起AlertDialog或者PopupWindow,我在上一篇博客中也總結了這兩種對話框的使
Android jni開發資料--NDK環境搭建 android開發人員注意了 谷歌改良了ndk的開發流程,對於Windows環境下NDK的開發,如果
是不是總感覺自己的流量不夠用?流量都去哪兒了?仔細想想才發現,流量是在手機qq群裡流失了!我們現在手機裡的qq群越來越多,好多群友都喜歡發發圖片視頻,我們應
這篇文章繼續分析Android動畫的TimeInterpolator(插值器)和TypeEvaluator(估值器)的簡單實現,以及分別去自定義插值器和估值器。一,Tim