はじめに
他の画面には全く使わないけど1画面だけパーティクルとか出したいみたいな需要が発生してそこのためにUnityとかを使ったらいけないかなぁ…と思ったのでこれを下地に作っていけないかなというやつです
テンプレートはEmptyActivityを選択した状態から開発していきます
Fragment用のレイアウトファイルを作る
Fragmentで使うレイアウトファイルを用意します。下記のようにシンプルなものを使います
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/anim_fragment_body"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</LinearLayout>
Fragmentを作成する
一旦Activityで読み込むようにしたいのでシンプルなFragmentを作成します
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
class AnimFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.fragment_anim, container, false)
}
}
MainActivity用のレイアウトファイルにFragmentを配置
表示確認したいのでFragmentを配置します。
activity_main.xmlを下記のように書き換えます。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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=".MainActivity"
android:baselineAligned="false">
<fragment
android:id="@+id/fragment"
android:name="io.github.tamfoi.fragmentcanvas.AnimFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
CustomView(Canvas)を作成してFragmentに表示
下記のようにFragmentを修正します。
やった作業
- CustomViewの作成
- CustomViewをFragmentのViewに追加
- CustomViewに四角を表示する
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.os.Bundle
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
class AnimFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_anim, container, false)
val layout = view.findViewById<LinearLayout>(R.id.anim_fragment_body)
layout.addView(AnimView(this.activity))
return view
}
class AnimView : View {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val paint = Paint()
paint.color = Color.BLACK
val rect = Rect(100, 200, 300, 400)
canvas!!.drawRect(rect, paint)
}
}
}
Animationするためのループを作る
下記のように編集してHandlerを使ってループ処理を作ります
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.os.Bundle
import android.os.Handler
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
class AnimFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_anim, container, false)
val layout = view.findViewById<LinearLayout>(R.id.anim_fragment_body)
val animView = AnimView(this.activity)
layout.addView(animView)
val handler = Handler()
handler.post(object : Runnable{
override fun run() {
animView.invalidate();
handler.postDelayed(this, 16);
}
})
return view
}
class AnimView : View {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val paint = Paint()
paint.color = Color.BLACK
val rect = Rect(100, 200, 300, 400)
canvas!!.drawRect(rect, paint)
}
}
}
Animationさせてみる
onDrawを下記のように編集してみます
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Rect
import android.os.Bundle
import android.os.Handler
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import kotlin.math.roundToInt
import kotlin.math.sin
class AnimFragment : Fragment() {
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.fragment_anim, container, false)
val layout = view.findViewById<LinearLayout>(R.id.anim_fragment_body)
val animView = AnimView(this.activity)
layout.addView(animView)
val handler = Handler()
handler.post(object : Runnable{
override fun run() {
animView.invalidate();
handler.postDelayed(this, 16);
}
})
return view
}
class AnimView : View {
constructor(context: Context?) : super(context)
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
val paint = Paint()
paint.color = Color.BLACK
val rect = Rect(400, 600, 700, 900)
val offsetY = sin(System.currentTimeMillis().toDouble() * 0.005) * 500
rect.offset(0, offsetY.roundToInt())
canvas!!.drawRect(rect, paint)
}
}
}
下記のようになりました(sinの動き楽しいですね)
おわりに
実際のところパフォーマンス的にどうなのか分からないのでこうしたほうが良いよみたいなのあったら知りたいです
参考
http://muumuutech.hatenablog.com/entry/2017/10/29/163705
https://stackoverflow.com/questions/23280685/drawing-in-a-fragment-in-android/23282354#23282354
http://blog.livedoor.jp/stock_club/archives/52105545.html
https://tech.recruit-mp.co.jp/mobile/remember_canvas1/
https://sites.google.com/a/asabon.net/asabon_site/android_programming/coding/ondraw
https://qiita.com/aftercider/items/81edf35993c2df3de353