編輯:關於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 DialogFragment對話框
寫在前面從事Android開發至今,一提及Android開發中使用的對話框就想起AlertDialog或者PopupWindow,我在上一篇博客中也總結了這兩種對話框的使
android JNI調用
Android jni開發資料--NDK環境搭建 android開發人員注意了 谷歌改良了ndk的開發流程,對於Windows環境下NDK的開發,如果
手機qq如何節省流量
是不是總感覺自己的流量不夠用?流量都去哪兒了?仔細想想才發現,流量是在手機qq群裡流失了!我們現在手機裡的qq群越來越多,好多群友都喜歡發發圖片視頻,我們應
Android動畫TimeInterpolator(插值器)和TypeEvaluator(估值器)分析
這篇文章繼續分析Android動畫的TimeInterpolator(插值器)和TypeEvaluator(估值器)的簡單實現,以及分別去自定義插值器和估值器。一,Tim