スキップしてメイン コンテンツに移動

android.graphics.Pathで紙が浮いてるような影を描画する

なかなかオリジナリティ溢れるやり方なんですが、紙が浮いてるような影が付いてる画像をGoogleで画像検索して、その画像を拡大しておそらくこうなってるだろうとpathで表現してみました。ただ単に影を付けるなら、PaintのsetShadowLayer()を利用すればすぐに付けられますが、今回はこのような



両端がちょっと浮いてるような影についてです。

また、Pathで描画するメリットは、
  • Android API Level 1からサポートされてる
  • 自由に座標を指定できるので、端末のサイズ等に合せて調節できるなど
があると思われます。座標を計算するのがややこしいですけど。



描画のベースとなるActivityは背景色を#eeeにして#FFFFFFFFの四角をViewを継承したクラスで描画します。


Viewを継承したクラスは、

public static class SampleView extends View {

    public SampleView(Context context) {
        super(context);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.parseColor("#FFFFFFFF"));

        // 紙
        canvas.drawRect(100, 100, 400, 300, paint);

    }
}

これを基に、影を付けていきたいと思います。

まずは影となる黒色の三角を、白四角の下に鋭い黒三角としてPathで描画します。onDrawの中身は、
Path lpath = new Path();
lpath.moveTo(115, 300);
lpath.lineTo(250, 298);
lpath.lineTo(115, 308);

Paint lpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
lpaint.setStyle(Paint.Style.FILL);
lpaint.setColor(Color.parseColor("#ff000000"));

canvas.drawPath(lpath, lpaint);

Path rpath = new Path();
rpath.moveTo(385, 300);
rpath.lineTo(250, 298);
rpath.lineTo(385, 308);

Paint rpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rpaint.setStyle(Paint.Style.FILL);
rpaint.setColor(Color.parseColor("#ff000000"));

canvas.drawPath(rpath, rpaint);


Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#FFFFFFFF"));

// 紙
canvas.drawRect(100, 100, 400, 300, paint);


もうこの時点で若干影っぽいです。濃いめの背景の場合はこれでも良いかもしれません。あと、lpath.lineTo(250, 298);ですが、白四角に黒四角を若干めり込ませる軌跡をたどってます。何故そうする必要があるのか?と言う点については後ほど記述します。

このままでは黒い影が主張しすぎるので、色を薄めます。#ff000000としている部分を#99000000で少し透過させます。



はい、気持ち薄くなりましたね。で、これに、BlurMaskFilterをセットして、黒四角をぼかします。onDrawの全体像はこんな感じ。

Path lpath = new Path();
lpath.moveTo(115, 300);
lpath.lineTo(250, 298);
lpath.lineTo(115, 308);

Paint lpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
lpaint.setStyle(Paint.Style.FILL);

lpaint.setColor(Color.parseColor("#99000000"));

MaskFilter  mlBlur = new BlurMaskFilter(2, BlurMaskFilter.Blur.NORMAL);
lpaint.setMaskFilter(mlBlur);

canvas.drawPath(lpath, lpaint);

Path rpath = new Path();

rpath.moveTo(385, 300);
rpath.lineTo(250, 298);
rpath.lineTo(385, 308);

Paint rpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
rpaint.setStyle(Paint.Style.FILL);

rpaint.setColor(Color.parseColor("#99000000"));

MaskFilter mrBlur = new BlurMaskFilter(2, BlurMaskFilter.Blur.NORMAL);
rpaint.setMaskFilter(mrBlur);

canvas.drawPath(rpath, rpaint);

Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.parseColor("#FFFFFFFF"));

// 紙
canvas.drawRect(100, 100, 400, 300, paint);

で、できあがりです。


先ほどの、「白四角に黒四角を若干めり込ませる」はこのBlurMaskFilterをBlurMaskFilter.Blur.NORMALでぼかすと、線がにじむため、紙の下全体が浮いたようになりしまりが悪くなるための帳尻合せです。

あと、この紙の部分も白ではなく若干色を付けてBlurMaskFilter.Blur.INNERでぼかしてやると、ちょっと厚みのある紙になります。などと好みに合わてちょっと手を加えればより見栄えがよくなるのではと思います。


コメント

このブログの人気の投稿

GolangでWindows GUIアプリケーション

GUIアプリ作成の前提 社内ツールとしてexeで配布 開発環境はGoLandを使う 社内ツールとしてexeを配布ということであれば、Visual StudioでC#による開発だと思います。しかしながら、Go言語を習得したいのと、GoLandの補完機能が便利で、Android Studio使っていたこともあり、とっつきやすいという点からGo縛りでGUIアプリケーションを考えたいと思います。 lxn/walk Windows application library kit for Go. Windows向けしか考えていないので、まずこのライブラリなのですが、ボタンやコンボボックスが思ったように並ばなかったり、手軽にイメージボタンを配置したりなど、簡単にレイアウトを変更できない課題に直面しました。レイアウト作成だけで時間を取られてしまいます。そう言えば、Androidアプリ開発のときは、XMLでデザイン部分を切り離してたのを思い出して、今回の調査の運びとなりました。 fyne-io/fyne Cross platform native GUIs designed for Go based on Material Design. Supports: Linux, macOS, Windows, BSD, iOS and Android. walkと比べると、クロスプラットフォームで作成できるのですが、こちらもコードの中にデザインを書いていく形でした。 therecipe/qt therecipe/qt allows you to write Qt applications entirely in Go or JavaScript. Qt Creatorなるものがあるようで、デザイン部分を切り離せる印象はあるものの、最新のPCでもビルドに時間がかかるようで、学習コストもかかるという記事を見かけて断念しました。 どうしたものかとツイートしましたら、下記のようにご助言をいただいた。 同じ課題に対し色々試した結果、PWAのフルキャッシュドに落ち着いた。中身はGo+WASMで。 https://t.co/e60whDTV16 — のぼのぼ📡 (@nobonobo) July 21, 2020 PWA 早速調べてみました。Googleが進めているプロジェクトで、ネイティブアプリのよ

Javaでprivateなfieldやmethodにアクセスする

JUnitでテストしてると、privateなフィールドにアクセスして、値を参照したりセットしたりしたくなるわけですが、よく使うのでメモしておきます。 例えば、次のような対象のクラスがあるとします。 public class ParentClass { private String hoge = "ParentClass!!"; public void dispMsg() { System.out.println("dispMsg:" + hoge); } private void privateDispMsg(String msg) { System.out.println("dispMsg:" + msg); } }

Eclipseで一通り基本的なGitを使ってみる

備忘録的にまとめておきたいと思います。おかしな点があればご指摘いただければ幸いです。 目次 環境 プロジェクト作成~初コミットまで コミットの履歴&差分を見る 元に戻す ブランチについて ブランチを作成してみる ブランチを統合するには マージする Rebaseする ローカルリポジトリからプロジェクトを取り込む コミットしたメッセージの修正 環境 Eclipse IDE for Java Developers:Juno Service Release 1 Git:上記Eclipseのプリインストール版