質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

Q&A

解決済

2回答

941閲覧

Androidでパターンロックを作りたい

sena14

総合スコア109

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Android Studio

Android Studioは、 Google社によって開発された、 Androidのネイティブアプリケーション開発に特化した統合開発ツールです。

Kotlin

Kotlinは、ジェットブレインズ社のアンドリー・ブレスラフ、ドミトリー・ジェメロフが開発した、 静的型付けのオブジェクト指向プログラミング言語です。

0グッド

0クリップ

投稿2019/02/13 07:19

Androidでパターンロックのようなものを作りたいです。

・3×3のViewを配置
・なぞるとその軌跡がわかる
・一度触ったところは触れない

とりあえず正解と一致などは無視して表面的なものだけ作りたいです。

調べてみたのですがタップされたイベントの取得しかわかりませんでした。Viewがどのようになぞられたか検知する方法で参考になるものが見つからず最初から詰まってしまい困っています。

どのように実装できるのか、また参考になるものがあれば教えていただきたいです。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

荒削りですが, サンプルになればと View を作ってみました.
1つの View 内でドットを 9 つ書いて, 線を引いています.
PatternLockView.OnDotTouchListener を登録すると, ドットに接触する毎にその番号が通知されます.
View を 3x3 に置いてその上に透明な View を置いた場合もこのような処理は必要になると思われますので, 3x3 に置いた View の役割が無いと思います.

java

1package com.example.patternlock; 2 3import android.content.Context; 4import android.graphics.*; 5import android.support.annotation.Nullable; 6import android.util.AttributeSet; 7import android.view.*; 8import java.util.*; 9 10public class PatternLockView extends View implements View.OnTouchListener { 11 public PatternLockView(Context context) { 12 super(context); 13 initialize(); 14 } 15 public PatternLockView(Context context, @Nullable AttributeSet attrs) { 16 super(context, attrs); 17 initialize(); 18 } 19 public PatternLockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 20 super(context, attrs, defStyleAttr); 21 initialize(); 22 } 23 public PatternLockView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { 24 super(context, attrs, defStyleAttr, defStyleRes); 25 initialize(); 26 } 27 private void initialize() { 28 setOnTouchListener(this); 29 } 30 31 interface OnDotTouchListener { 32 /** 33 * index番目のドットに触れた 34 * @param view 送信元View 35 * @param action 発生したアクション. MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE, MotionEvent.ACTION_UP 36 * @param index ドット位置. 37 * action=MotionEvent.ACTION_DOWN || MotionEvent.ACTION_MOVE の場合: 0[左上],1[中央上],2[右上], 3[左中央],4[中央],5[右中央], 6[左下],7[中央下],8[右下] 38 * action=MotionEvent.ACTION_UP の場合: -1 39 */ 40 void onDotTouch(View view, int action, int index); 41 } 42 private OnDotTouchListener listener; 43 void setOnDotTouchListener(OnDotTouchListener listener) { 44 this.listener = listener; 45 } 46 47 private class Dot { 48 private int SIZE = 40; //[pixel] 49 final Point point; //中心位置(path用) 50 final Rect rect; //描画する矩形 51 Dot(int x, int y) { 52 point = new Point(x, y); 53 rect = new Rect(x-SIZE/2, y-SIZE/2, x+SIZE/2, y+SIZE/2); 54 } 55 } 56 /** 各ドット */ 57 private ArrayList<Dot> dots; 58 /** タッチ済みのドットの dots index (0~8) */ 59 private Set<Integer> touched = new HashSet<Integer>(); 60 61 private boolean tracking; 62 private Path path; 63 private Point lastDotPoint; 64 private int currentTouchX; 65 private int currentTouchY; 66 67 @Override 68 protected void onDraw(Canvas canvas) { 69 super.onDraw(canvas); 70 71 if(dots == null) { 72 int w = canvas.getWidth(); 73 int h = canvas.getHeight(); 74 75 int[] x = {h / 4, h / 2, h - h / 4}; 76 int[] y = {w / 4, w / 2, w - w / 4}; 77 dots = new ArrayList<Dot>(); 78 for (int i = 0; i < y.length; i++) { 79 for (int j = 0; j < x.length; j++) { 80 dots.add(new Dot(x[j], y[i])); 81 } 82 } 83 } 84 85 Paint paint = new Paint(); 86 paint.setAntiAlias(true); 87 88 paint.setColor(Color.RED); 89 paint.setStyle(Paint.Style.FILL); 90 for (Dot dot : dots) canvas.drawRect(dot.rect, paint); 91 92 if(path != null) { 93 paint.setColor(Color.GREEN); 94 paint.setStyle(Paint.Style.STROKE); 95 paint.setStrokeWidth(10); 96 canvas.drawPath(path, paint); 97 } 98 if(lastDotPoint != null) { 99 paint.setColor(Color.BLUE); 100 paint.setStyle(Paint.Style.STROKE); 101 paint.setStrokeWidth(10); 102 Path currentPath = new Path(); 103 currentPath.moveTo(lastDotPoint.x, lastDotPoint.y); 104 currentPath.lineTo(currentTouchX, currentTouchY); 105 canvas.drawPath(currentPath, paint); 106 } 107 } 108 109 @Override 110 public boolean onTouch(View v, MotionEvent event) { 111 int action = event.getAction(); 112 if(action == MotionEvent.ACTION_DOWN || (tracking && action == MotionEvent.ACTION_MOVE)) { 113 currentTouchX = (int)event.getX(); 114 currentTouchY = (int)event.getY(); 115 int index = searchDotIndex((int)event.getX(), (int)event.getY()); 116 if(index != -1 && !touched.contains(index)) { //未タッチのドット 117 touched.add(index); 118 if (listener != null) { 119 lastDotPoint = dots.get(index).point; 120 if (action == MotionEvent.ACTION_DOWN) { 121 path = new Path(); 122 path.moveTo(dots.get(index).point.x, dots.get(index).point.y); 123 } else { 124 path.lineTo(dots.get(index).point.x, dots.get(index).point.y); 125 } 126 listener.onDotTouch(this, event.getAction(), index); 127 tracking = true; 128 } 129 } 130 invalidate(); 131 return true; 132 } else if(tracking && action == MotionEvent.ACTION_UP) { 133 if(listener != null) { 134 listener.onDotTouch(this, event.getAction(), -1); 135 tracking = false; 136 touched.clear(); 137 lastDotPoint = null; 138 } 139 return true; 140 } 141 return false; 142 } 143 144 private int searchDotIndex(int x, int y) { 145 for(int i=0; i<dots.size(); i++) { 146 if(dots.get(i).rect.contains(x,y)) return i; 147 } 148 return -1; //無し 149 } 150}

java

1package com.example.patternlock; 2 3import android.os.Bundle; 4import android.support.v7.app.AppCompatActivity; 5import android.util.Log; 6import android.view.View; 7 8public class MainActivity extends AppCompatActivity { 9 @Override 10 protected void onCreate(Bundle savedInstanceState) { 11 super.onCreate(savedInstanceState); 12 setContentView(R.layout.activity_main); 13 14 PatternLockView patternLockView = findViewById(R.id.patternLockView); 15 patternLockView.setOnDotTouchListener(new PatternLockView.OnDotTouchListener() { 16 @Override 17 public void onDotTouch(View view, int action, int index) { 18 Log.d("onDotTouch","action="+action+", index="+index); 19 } 20 }); 21 } 22}

XML

1<?xml version="1.0" encoding="utf-8"?> 2<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:app="http://schemas.android.com/apk/res-auto" 4 xmlns:tools="http://schemas.android.com/tools" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent" 7 tools:context=".MainActivity"> 8 9 <com.example.patternlock.PatternLockView 10 android:layout_width="300dp" 11 android:layout_height="300dp" 12 android:id="@+id/patternLockView" 13 app:layout_constraintBottom_toBottomOf="parent" 14 app:layout_constraintLeft_toLeftOf="parent" 15 app:layout_constraintRight_toRightOf="parent" 16 app:layout_constraintTop_toTopOf="parent" 17 /> 18 19</android.support.constraint.ConstraintLayout>

投稿2019/02/13 17:23

編集2019/02/14 05:22
jimbe

総合スコア12545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sena14

2019/02/14 04:38

ありがとうございます。 一度じっくり読ませていただきます。
jimbe

2019/02/14 09:00

エミュレータで試していたのですが, 実機ですとドットが小さいかもしれません. 内部クラスの Dot にある SIZE=40 (大文字ですが final を付け忘れています 汗) を 80 や 100 等にすると, タッチし易いかもしれません.
sena14

2019/02/20 05:59

ありがとうございます。 この方針でなんとなくできそうです!
guest

0

投稿2019/02/13 08:33

jimbe

総合スコア12545

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sena14

2019/02/13 08:59 編集

すみません。 知識が浅くこれでどのようにそれぞれのViewをなぞるというのを検知すればいいのか分かりません。 どのような方針で進めればいいのか教えていただけると助かります。
jimbe

2019/02/13 09:17

まず, ご紹介したリンク先の記事・プログラムをご理解されるのが先かと思います. このお絵かきプログラムではどのようにして指の動きに応じて線が引かれているのかがお分かりになれば, 次に(ドットを3x3の形に描画しまして)「ドット間のみ線を引く」という改造に進めるかと思います. ドット間に線が引かれるようになれば, 「一度通ったドットに二度は通れない」に進めると思います.
jimbe

2019/02/13 09:19

「ドットの書かれた View が 3x3 に並んでいる」という解釈とは違う方法をご紹介しています. 「View は一つで, 中に 3x3 のドットが書かれている」中を線を引く方法です.
sena14

2019/02/13 09:54

座標を取得し線を引いているということですよね? 座標を扱わずに実装したいので 「ドットの書かれた View が 3x3 に並んでいる」という前提のもと実装したいです。 そのための方法を教えていただけると助かります。
jimbe

2019/02/13 12:13 編集

座標を扱わずにとなりますと, 外から実装が見えないようにライブラリ化されたものをお探しということになると思いますので, すみません, 私はそのようなライブラリを存じません. 見当違いでお手数おかけして申し訳ありません.
sena14

2019/02/13 13:28

そうなんですね。座標を使わないと実装困難なんですね。 座標を使う場合Viewが座標のどの範囲を占めているかというのはどのように判定すればいいのでしょうか? 教えていただいたサイトではその部分がかかれていなくてそもそもドット間の判定方法が分かっていないので改造に進む方法が見えていません。 よろしくお願いします。
jimbe

2019/02/13 13:59

なぞりを検出する onTouch で(onClick 等と違いまして)座標が送られてきています. また, なぞりを開始した View に対してのみ, 以降の移動や指を離したイベントが通知されるようです. それぞれ通知される座標はその View の左上を 0,0 とした座標ですので, 画面の座標に変換する等を行い View のツリーから該当する View を探す処理が必要となります. なぞりの対象として複数の View を用いますとこのような処理が必要になりますが, 一つの View 内であれば座標はその範囲内に収まるはずですので, 変換等が不要になります.
sena14

2019/02/13 14:50

要は3×3のViewを配置したレイアウトの上に透明な画面いっぱいなレイアウトを重ねて、透明なレイアウトでOnTouchListnerを使えばいいということですよね? その場合下の3×3で表示しているどのViewの上を通っているのかというのは透明なレイアウトの座標からどのように算出することができるのでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問