ViewPagerを使ってCanvasにお絵かきしてみる[その2]

さて今回は、前回作成したViewに対して描画を行っていきます。
アプリの骨組みは前回記事で記述していますので、まだ見られていない方はまずそちらを参照ください。

CustViewPager.java
    private Paint paint;
    private Path path;
    private ArrayList<path> pathList = new ArrayList<path>();

    public CustViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setStyle(Paint.Style.STROKE);
        paint.setAntiAlias(true);
        paint.setStrokeWidth(10);
        paint.setColor(Color.BLACK);
    }


CustViewPager.java

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        for (int i=0; i &lt; pathList.size(); i++) {
            canvas.drawPath(pathList.get(i), paint);
        }
    }

CustViewPager.java


    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path = new Path();
                path.moveTo(event.getX(), event.getY());
                pathList.add(path);
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(event.getX(), event.getY());
                invalidate();
            case MotionEvent.ACTION_UP:
                path.lineTo(event.getX(), event.getY());
                invalidate();
                break;
            default:
        }
        return super.onTouchEvent(event);
    }


ここまでで描画が出来、且つ、左右フリックでページ切替が出来る様になりました。
但し、以下問題が発生しているので、その対策を行っていきます。

問題①
右ページで描画した内容が、左ページに表示されている

原因:
onDraw()で描画しているCanvasは、ページ毎に用意しているわけではなく、ページ分連なった1つのCanvasです。
一方、onTouchEventで取得される座標(x , y)は(0 ,0)からとなるため、2ページ目で描画しても1ページ目に描画されてしまいます。

対策:
onTouchEventに実装している、path.moveTo()とpath.lineTo()のX座標に画面幅を足すことで解決する。

CustViewPager.java

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        /* 描画開始座標オフセット */
        int offset = 0;

        /* 2ページ目の場合 */
        if(mPage == 1) {
            offset = 1435;  //画面幅サイズを指定する(今回はサンプルとして直値)
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path = new Path();
                path.moveTo(event.getX()+offset, event.getY());
                pathList.add(path);
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(event.getX()+offset, event.getY());
                invalidate();
                break;
            case MotionEvent.ACTION_UP:
                path.lineTo(event.getX()+offset, event.getY());
                invalidate();
                break;
            default:
        }
        return super.onTouchEvent(event);
    }
CustViewPager.java

    private int mPage = 0;

    public void setPage(int page) {
        mPage = page;
    }

MainActivity.java

/**
/* 1ページ目表示の時は以下をCall */
setPage(0);

/* 2ページ目表示の時は以下をCall */
setPage(1);

*/


問題②
左右フリックで描画と画面切替が同時に発生する

対策:
ViewPagerを使用しているので、フリックで画面が切替出来る様になるのは当然ですが、
今回描画を行うので、左右のモーションは画面切替ではなく、描画だけに限定したい。

色々な方のサイトを漁ってみましたが、大体がonTouchEventの戻り値をfalseにするとしか記述がありませんでしたが、調査した結果、以下の様にすることで解決ができました。

CustViewPager.java

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int offset = 0;
        if(mPage == 1) {
            offset = 1435;
        }
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                path = new Path();
                path.moveTo(event.getX()+offset, event.getY());
                pathList.add(path);
                break;
            case MotionEvent.ACTION_MOVE:
                path.lineTo(event.getX()+offset, event.getY());
                invalidate();
                return false; /* ★★★ ここでfalseにする */
            case MotionEvent.ACTION_UP:
                path.lineTo(event.getX()+offset, event.getY());
                invalidate();
                break;
            default:
        }
        return super.onTouchEvent(event);
    }

onTouchEventの戻り値を一律falseにしてしまうと、ACTION_DOWNしかイベントは飛んできません。
なので、ACTION_MOVEのイベントが来た時にfalseを返すようにします。
こうすることで、ViewPagerのフリックで画面切替が止まり、また、描画は実現が出来ます。

以上で、ViewPagerで画面切替を行い、且つ、描画を行うサンプルコードとなります。

前回記事の初めに示した動画では、色の指定や、描画クリアなど色々としておりますが、
paintやpathListに対して加工するだけなので、特にここでは扱いません。
もしご要望があれば回答致しますのでご連絡いただければと思います。

ここまで査読いただきありがとうございます。

mana99 について

30代のシステムエンジニア 仕事以外にAndroidアプリを定期的にリリース モットーは「最短&シンプル」
カテゴリー: ノウハウ タグ: , , , , パーマリンク