はじめに
View が Screen に表示されたか判定する処理を作成します。例えば Player が Screen に表示されたら動画の再生を開始したい、TextView が表示されたらテキストカラーを変えたい、といった処理に使えるサンプルを作成してみたいと思います。
TL;DR
表示されたか判定する方法はシンプルです、 Screen の Rectと View の Rect を取得して、 Screen の Rectに View のRect が含まれているか判定するだけです。
1. Screen の範囲(Rect)を取得する
private fun getScreenRect() : Rect {
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
return Rect(0, 0, displayMetrics.widthPixels,displayMetrics.heightPixels)
}
2. View の範囲(Rect)を取得する
private fun View.getViewRect() : Rect {
val array = IntArray(2)
this.getLocationOnScreen(array)
return Rect(this.width, this.height, array[0], array[1])
}
3. Screen に View に表示されているか判定する
scroll_view.viewTreeObserver.addOnScrollChangedListener {
val screenRect = getScreenRect()
val oneRect = one.getViewRect()
if (screenRect.contains(oneRect)) {
// 含まれているときの処理
}
else {
// 含まれていないときの処理
}
レイアウトの準備する
判定処理を記述するためにスクロールしなければスクリーンに表示できないようなレイアウトを作成します。ScrollView の中に TextView が3つ含まれているレイアウトを準備しておきましょう。
<ScrollView android:id="@+id/scroll_view"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/linear_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/one"
android:layout_width="match_parent"
android:layout_height="200dp"
android:textAlignment="center"
android:textSize="80sp"
android:text="One" />
︙
</LinearLayout>
</ScrollView>
Screen の範囲(Rect)を取得する
Screen の位置(サイズ)は windowsManager.defaultDisplay.getMetrics()
に取得できます。このgetMetrics
で取得した幅と高さを利用して、Screen の範囲を示す Rect
オブジェクトを作成しましょう。(ここで取得できるサイズは Pixel になります)
private fun getScreenRect() : Rect {
val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
return Rect(0, 0, displayMetrics.widthPixels,displayMetrics.heightPixels)
}
View の範囲(Rect)を取得する
View の左上の座標をView.getLocationInWindow
で取得できます。また View の高さと幅は View.width
と View.height
で取得できます。これらの値を組み合わせて View が表示されている範囲を示す Rect
オブジェクトを作成しましょう。(ここも取得できるサイズは Pixel になります)
private fun View.getViewRect() : Rect {
val array = IntArray(2)
this.getLocationOnScreen(array)
return Rect(this.width, this.height, array[0], array[1])
}
Screen に View に表示されているか判定する
あとは ScrollView のスクロール位置が更新された時、Screen に View が表示されているか判定する処理を記述すれば完成となります。判定処理を記述する箇所は ScrollView
の viewTreeObserver
に addOnScrollChangedListener
になります。そこに Screen の範囲(Rect)に View の範囲(Rect)が含まれるか判定する処理を記述していきます。(含まれるか判定するには Rect の contains が便利です、含まているかそうでないかを Boolean で返すメソッドになります。)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val oneTextView = one
val twoTextView = two
val threeTextView = three
scroll_view.viewTreeObserver.addOnScrollChangedListener {
val screenRect = getScreenRect()
val oneRect = one.getViewRect()
val oneColor = if (screenRect.contains(oneRect)) {
Color.RED
} else {
Color.WHITE
}
oneTextView.setBackgroundColor(oneColor)
val twoRect = twoTextView.getViewRect()
val twoColor = if (screenRect.contains(twoRect)) {
Color.RED
} else {
Color.WHITE
}
twoTextView.setBackgroundColor(twoColor)
val threeRect = threeTextView.getViewRect()
val threeColor = if (screenRect.contains(threeRect)) {
Color.RED
} else {
Color.WHITE
}
threeTextView.setBackgroundColor(threeColor)
}
}