LoginSignup
13
13

More than 5 years have passed since last update.

Androidアプリで画面サイズに依存しないcm指定の入出力

Last updated at Posted at 2016-02-03

多くのAndroidアプリは画面サイズが変われば表示されるアプリの大きさも変わります。
しかし、(稀だとは思いますが)アプリによっては画面サイズに関わらず1cmの大きさなら1cmの大きさの入出力をしなければならない場合があると思います。

先日、私が作った曲線定規というアプリでは実際のサイズの入出力が必要でしたのでその時に使った方法を紹介します。

曲線定規.png
曲線定規

このアプリでは、まず背景が1cm四方の四角形になっています。
画面が大きくなったからといって1cm四方が崩れては定規として成り立たなくなってしまいます。
画面のサイズに依存しない描画が求められています。
また、画面をなぞって線を書くとその線の長さも表示されます。

1cm四方の正方形を描く方法

まず背景に四角を描画します。
わたしはこちら(http://android.keicode.com/basics/ui-canvas-simple-rect.php)を参考にしました。

MainActivity.java

MainActivity.java
import android.app.Activity;
import android.os.Bundle;

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

CanvasTest1View.java

CanvasTest1View.java
public class CanvasTest1View extends View {
    private Rect rect;
    private Paint paint;
    public CanvasTest1View(Context context) {
        super(context);
        rect = new Rect();
        paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);//直線
        paint.setStrokeWidth(10);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRect(rect, paint);
        rect.set(10, 10, 200, 200);
        invalidate();
    }

}

2.png

rect.set(10, 10, 200, 200);
をループなどを使い複数実行することで方眼を作ることができます。
今書かれている四角は縦横200ピクセルの四角となっています。
ピクセルとは機種ごとの大きさになっていて、
極端に言うと400×400ピクセルの四角い画面を持ったandroidがあったとすれば
画面の1/4をこの四角が占めるということになります。

今回は1cmの四角を書いていきたいので1cmが何ピクセルか調べる必要があります。
1cmが何ピクセルかを調べるにはまずdpiを求めなければなりません。
dpiとはドットパーインチの略で、1インチの直線を書くのに何ピクセルを必要とするかという単位です。

まず、端末の1dpiを調べます
public float dpi = main.getResources().getDisplayMetrics().densityDpi;

最近はxxhdpiを採用している端末が多いので
dpiには480が入ることが多いと思います。
つまり、1インチ(2.54cm)は480ピクセルということになります。
ということは、
480/2.54=188.976378
約188.9ピクセルが1cmということになります。
これを踏まえてソースを変更します。

まず、1cmが何ピクセルか調べるクラスを作成します。

CalcDpi.java

CalcDpi.java
import android.app.Activity;
import android.os.Bundle;

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

先ほど書いたソースを変更してCalcDpiを使用します。

MainActivity.java

MainActivity.java
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new CanvasTest1View(this,this));
    }
}

CanvasTest1View.java

CanvasTest1View.java
import android.graphics.Color;
import android.view.View;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;

public class CanvasTest1View extends View {
    private Rect rect;
    private Paint paint;

    private CalcDpi calcdpi;

    public CanvasTest1View(Context context,MainActivity main) {
        super(context);
        rect = new Rect();
        paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);//直線
        paint.setStrokeWidth(10);

        calcdpi = new CalcDpi(main);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRect(rect, paint);

        rect.set(10, 10, (int)calcdpi.getPxTocm(),(int)calcdpi.getPxTocm());
        invalidate();
    }
}

3.png

あまり違いはわかりませんがw
1cmの四角形を描画することができました。

入力した幅をcm単位で取得する方法

次に画面をなぞった長さをcmで取得する方法を説明します。
参考にしたサイトはコチラ
http://android.keicode.com/basics/ui-canvas-path.php
です。
先ほどと同じかたの記事です。Oyama氏感謝します。

dpi→cmは先ほどのCalcDpiクラスを流用します。
MainActivityもそのままです。

CanvasTest2View.java

CanvasTest2View.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class CanvasTest2View extends View {
    private Paint paint;
    private Path path;
    private float startX;
    private float startY;
    private float endX;
    private float endY;
    private CalcDpi calcDpi;

    public CanvasTest2View(Context context,MainActivity main) {
        super(context);
        path = new Path();
        paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(10);
        calcDpi = new CalcDpi(main);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawPath(path, paint);
        float tatePx = endX - startX;
        float yokoPx = endY - startY;
        double tateCm = Math.sqrt(tatePx*tatePx)/calcDpi.getPxTocm();
        double yokoCm = Math.sqrt(yokoPx*yokoPx)/calcDpi.getPxTocm();

        Log.d("タテ幅", String.valueOf(tateCm));
        Log.d("ヨコ幅", String.valueOf(yokoCm));

    }

    @Override public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX();
        float y = event.getY();
        switch(event.getAction()){
            case MotionEvent.ACTION_DOWN:
                path.moveTo(x, y);
                invalidate();
                startX = x;
                startY = y;
                endX = x;
                endY = y;
                break;
            case MotionEvent.ACTION_UP:
                path.lineTo(x, y);
                invalidate();
                endX = x;
                endY = y;
                break;
        }
        return true;
    }
}

これでタテ幅ヨコ幅をcmで取得することができます。

誰かの参考になれば幸いです。
冒頭で紹介したわたしの曲線定規もgithubとGoogleplayでソースとアプリを公開しておりますので、
ダウンロードしてみていただくと参考になると思います。

Github
https://github.com/kuniatsu/RulerPad

Googleplay
https://play.google.com/store/apps/details?id=com.xample.ux21a.rulerpad

13
13
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
13