Androidでパターンロックのようなものを作りたいです。
・3×3のViewを配置
・なぞるとその軌跡がわかる
・一度触ったところは触れない
とりあえず正解と一致などは無視して表面的なものだけ作りたいです。
調べてみたのですがタップされたイベントの取得しかわかりませんでした。Viewがどのようになぞられたか検知する方法で参考になるものが見つからず最初から詰まってしまい困っています。
どのように実装できるのか、また参考になるものがあれば教えていただきたいです。
よろしくお願いします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答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総合スコア12545
0
以下は如何でしょう.
投稿2019/02/13 08:33
総合スコア12545
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/13 09:17
2019/02/13 09:19
2019/02/13 09:54
2019/02/13 12:13 編集
2019/02/13 13:28
2019/02/13 13:59
2019/02/13 14:50
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/02/14 04:38
2019/02/14 09:00
2019/02/20 05:59