スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。



Androidで直線グラデーションを描画するポイント

Androidだと座標がintからfloatに変わったのと
解像度によって画面の大きさを拡大・縮小するため
連続した塗りつぶしをすると,細い線が空いてしまう。

なのでグラデーションを使用していた箇所がプツプツと途切れて
汚くなってしまうのでAndroid特有のグラデーションの塗りつぶしを使うことにしてみた。

グラデーションの種類(円や円環)がいくつかあるけど
今回使用するのは直線グラデーション。

結果はこちら...
device-2012-10-06-131913.png

グラデーションクラスLinearGradientに渡す開始・終了座標は後から変えることができないので
変更が必要なとき再生成する必要がある...。

描画で使用するものを描画の度に再生成なんて
現実的じゃないので,他にやる方法はないかと検証してみました。

グラデーションクラスに渡す座標は
Canvasの座標変換(translate)には影響を受けないということがわかりました。

ってことは,LinearGradientクラスには幅または高さを渡しておいて,
塗りつぶすときにCanvas.translate()を実行すればいい
って使い方が現実的だろうな。

コードはこちら。
(検証用でコードは汚いですが...)

package com.example.gradationtest;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

public class GradationTestActivity extends Activity
{
	@Override public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(new ScreenView(this));
	}

	static private class ScreenView extends View
	{
		private final String tag = getClass().getSimpleName();
		
		private final LinearGradient linearGradient1;
		private final LinearGradient linearGradient2;
		private final LinearGradient linearGradient3;
		private final Paint paintBitmap;
		private final Paint paint1;
		private final Rect rect1;
		private final Rect rect2;
		private final Rect rect3;
		private final Rect rect4;
		private final Rect rect5;
		private final Rect rect6;
		
		static final private int HEIGHT = 30;
		static final private int MARGIN_X = 40;
		
		// 画面の大きさを取得
		private final DisplayMetrics dm;
		
		// 描画領域の幅
		private final float width;
		
		public ScreenView(Activity activity)
		{
			super(activity);
			
			dm = new DisplayMetrics();
			activity.getWindowManager().getDefaultDisplay().getMetrics(dm);
			
			// 描画領域の幅
			width = dm.widthPixels - (2*MARGIN_X);
			
			final float startX = 0;
			final float endX = width/4;
			final float endY = 0;
			
			Log.d(tag, "endX:" + endX + ", endY:" + endY);
			
			final int c0 = Color.RED;
			final int c1 = Color.BLUE;
			
			linearGradient1 = new LinearGradient(startX, 0, endX, endY, c0, c1, Shader.TileMode.CLAMP);
			linearGradient2 = new LinearGradient(startX, 0, endX, endY, c0, c1, Shader.TileMode.MIRROR);
			linearGradient3 = new LinearGradient(startX, 0, endX, endY, c0, c1, Shader.TileMode.REPEAT);

			Matrix matrix = new Matrix();
			linearGradient1.getLocalMatrix(matrix);
			Log.d(tag, "" + matrix);
			
			paint1 = new Paint(Paint.ANTI_ALIAS_FLAG);
			paint1.setShader(linearGradient1);
			paint1.setStyle(Paint.Style.FILL);
			paint1.setTextSize(40f);

			final int half = (int)width/2;
			final int quarter = (int)width/4;
			final int right = dm.widthPixels - (2*MARGIN_X);
			rect1 = new Rect(0, 0, right, HEIGHT);
			rect2 = new Rect(quarter, 0, right, HEIGHT);
			rect3 = new Rect(half, 0, right, HEIGHT);
			rect4 = new Rect(quarter, 0, right - quarter, HEIGHT);
			rect5 = new Rect(0, 0, half, HEIGHT);
			rect6 = new Rect(0, 0, half, HEIGHT);
			
			paintBitmap = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
		}

		@Override protected void onDraw(Canvas canvas)
		{
			super.onDraw(canvas);
			drawGradient(canvas);
		}
		
		private void drawGradient(Canvas c)
		{
			Bitmap bitmap = Bitmap.createBitmap(dm.widthPixels, dm.heightPixels, Bitmap.Config.ARGB_8888);
			bitmap.setDensity(DisplayMetrics.DENSITY_DEFAULT);
			
			Canvas canvas = new Canvas(bitmap);
			
			final int quarter = (int)width/4;
			
			canvas.drawColor(Color.BLACK);
			
			final float marginY = 10f;
			float y = marginY;

			final int saveCount0 = canvas.save();
			
			try
			{
				canvas.translate(MARGIN_X, y);
				paint1.setShader(linearGradient1);
				canvas.drawRect(rect1, paint1);
				
				y += HEIGHT;
				canvas.translate(0, y);
				canvas.drawRect(rect2, paint1);
				
				canvas.translate(0, y);
				canvas.drawRect(rect3, paint1);
				
				canvas.translate(0, y);
				canvas.drawRect(rect4, paint1);
				
				canvas.translate(0, y);
				canvas.drawRect(rect5, paint1);
				
				canvas.translate(0, y);
	
				final int saveCount1 = canvas.save();
	
				try
				{
					// x座標の開始位置を変換したときのグラデーションを確認する
					canvas.translate(quarter, 0);
					canvas.drawRect(rect6, paint1);
				}
				finally
				{
					canvas.restoreToCount(saveCount1);
				}
				
				canvas.translate(0, y);
				paint1.setShader(linearGradient2);
				canvas.drawRect(rect1, paint1);
				
				canvas.translate(0, y);
				paint1.setShader(linearGradient3);
				canvas.drawRect(rect1, paint1);
			}
			finally
			{
				canvas.restoreToCount(saveCount0);
			}

			// グラデーションの色をログに出力
			for(int i=0; i < width; i++)
			{
				final int color = bitmap.getPixel(MARGIN_X+i, (int)(marginY));
				Log.d(tag, "x:" + i + "(" + Integer.toHexString(color) + ")");
			}
			
			// グラデーション開始色を確認する
			// Memo) 文字列の描画位置は適当
			final int startColor = bitmap.getPixel(MARGIN_X, (int)(marginY));
			canvas.translate(MARGIN_X, (int)(marginY + (y * 10)));
			canvas.drawText(Integer.toHexString(startColor), 0, paint1.ascent(), paint1);
			
			Matrix matrix = new Matrix();
			c.drawBitmap(bitmap, matrix, paintBitmap);
		}
	}
}
関連記事
スポンサーサイト

テーマ : ゲーム開発
ジャンル : コンピュータ




コメントの投稿

非公開コメント

アクセス
あなたは
キーワード
カテゴリー
最近の記事
リンク
月別アーカイブ
ブロとも申請フォーム

この人とブロともになる

WEB検索
Google

RSSフィード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。