タイトルにある通り、画面をタッチするとキラキラしたりマークが出たりするあれをやりたいなぁと思って調べた内容をメモです。
ちなみに、iOS版はコチラ ※Objective-cです
AndroidはonTouchEventを使うみたいです。
まずはActivityクラスを継承したjavaクラスを作って、onTouchEventを実装します。
public class TapActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tap);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
return super.onTouchEvent(event);
}
}
これでpointXとpointYにタッチポイントのX座標とY座標が入りますね。
あとはこれを使って上手くやると。
例えば・・・
1.activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:id="@+id/tapLayout" ←idを付与
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="jp.***.***.***.***.TapActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</RelativeLayout>
2.TapActivity.java
public class TapActivity extends Activity {
//ViewGroupを定義
RelativeLayout tapLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//定義したViewGroupにxmlで付与したidでRelativeLayoutを代入
tapLayout = (RelativeLayout)findViewById(R.id.tapLayout)
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
//画面dpを取得して画像サイズを準備
float dp = getResources().getDisplayMetrics().density;
int imgSize = (int)(50 * dp);
//画像を設定
ImageView img = new ImageView(getApplicationContext());
img.setImageResource(R.drawable.マーク画像);
//ImageViewに画像サイズを設定
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imgSize, imgSize);
img.setLayoutParams(params);
//画像の真ん中にタッチポイントが来るように設定
img.setX(pointX-imgSize/2);
img.setY(pointY-imgSize/2);
img.setScaleType(ImageView.ScaleType.FIT_XY);
//画像を半分のサイズに縮小
img.setScaleX(0.5f);
img.setScaleY(0.5F);
//画像を描画
tapLayout.addView(img);
//0.3秒かけて元のサイズに拡大しながら透明になるアニメーション
ViewCompat.animate(img)
.setDuration(300)
.alpha(0)
.scaleX(1)
.scaleY(1)
.setListener(new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
}
@Override
public void onAnimationEnd(View view) {
//アニメーション終了時に削除
tapLayout.removeView(img);
}
@Override
public void onAnimationCancel(View view) {
}
}).start();
return super.onTouchEvent(event);
}
でもこれだとタップした時にエフェクトが出てカッコ悪いですね。。。
しかも、画面をタップしながら指を動かしてもついこない。
さらに、アプリ全体を通して画面タップにエフェクト出したい場合、全てのActivityにこんな記述してられないから、こいつを継承したActivityで各画面を実装したい。
こんな欲張りを全て叶えたのが以下です。
1.TapActivity.java
public class TapActivity extends Activity {
//ViewGroupを定義
ViewGroup viewGroup;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
//ViewGroupを受け取るメソッドを準備
public void setViewGroup(ViewGroup vg){
viewGroup = vg;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float pointX = event.getX();
float pointY = event.getY();
float dp = getResources().getDisplayMetrics().density;
int imgSize = (int)(50 * dp);
//switch文でアクションを分岐
switch (event.getAction()){
//画面タップ時
case MotionEvent.ACTION_DOWN:
break;
//画面から指が離れた時
case MotionEvent.ACTION_UP:
final ImageView img = new ImageView(getApplicationContext());
img.setImageResource(R.drawable.マーク画像);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imgSize, imgSize);
img.setLayoutParams(params);
img.setX(pointX-imgSize/2);
img.setY(pointY-imgSize/2);
img.setScaleType(ImageView.ScaleType.FIT_XY);
img.setScaleX(0.5f);
img.setScaleY(0.5F);
viewGroup.addView(img);
ViewCompat.animate(img)
.setDuration(300)
.alpha(0)
.scaleX(1)
.scaleY(1)
.setListener(new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
}
@Override
public void onAnimationEnd(View view) {
viewGroup.removeView(img);
}
@Override
public void onAnimationCancel(View view) {
}
}).start();
break;
//画面タップのまま指を動かした時
case MotionEvent.ACTION_MOVE:
final ImageView img2 = new ImageView(getApplicationContext());
img2.setImageResource(R.drawable.マーク画像);
LinearLayout.LayoutParams params2 = new LinearLayout.LayoutParams(imgSize, imgSize);
img2.setLayoutParams(params2);
img2.setX(pointX-imgSize/2);
img2.setY(pointY-imgSize/2);
img2.setScaleType(ImageView.ScaleType.FIT_XY);
viewGroup.addView(img2);
//0.3秒かけて縮小しながら透明になるアニメーション
ViewCompat.animate(img2)
.setDuration(300)
.alpha(0)
.scaleX(0.01f)
.scaleY(0.01f)
.setListener(new ViewPropertyAnimatorListener() {
@Override
public void onAnimationStart(View view) {
}
@Override
public void onAnimationEnd(View view) {
viewGroup.removeView(img2);
}
@Override
public void onAnimationCancel(View view) {
}
}).start();
break;
}
return super.onTouchEvent(event);
}
}
2.MainActivity.java
//TapActivityを継承
public class MainActivity extends TapActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//xmlファイルで付与したidでViewGroupを渡す
setViewGroup((RelativeLayout)findViewById(R.id.mainLayout));
}
}
これでタップしながら動いてもついて来るし、継承させても機能するようになりました。
ちなみに、Androidでは現在表示しているViewGroupを取得する方法がないらしく、継承させてエフェクトを描画させるのに結構苦労しました。
最終的には都度呼び出し側のonCreateで渡してもらうというあまりカッコよくない方法を取ってしまいましたが。。。
何か他に良いやり方をご存知の方がいらっしゃれば是非アドバイスください!