Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android開發之圖片處理框架(三)

Android開發之圖片處理框架(三)

編輯:關於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
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved