きっかけ
- 2019 Material Design Awardで入賞したTrip.comを見て、自動スクロールで画像を表示していて良い感じだなと思ったので試してみました。
動作環境
- Android Studio 3.5.2
- Android 10, 5
サンプルコードについて
- 画像の自動スクロール
- カスタムビューで実装する
画像の自動スクロール
画像の自動スクロール
activity_scroll_image_view.xml
<ImageView
android:id="@+id/sushi"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:scaleType="matrix"
android:src="@drawable/sushi"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
画像の自動スクロール
ScrollImagaeViewActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_scroll_imagae_view)
val image = findViewById<ImageView>(R.id.sushi)
image.doOnLayout {
var repeatCount = 0
// imageViewに格納したDrawableの幅を取得する
val drawableWidth = image.drawable.intrinsicWidth
val imageWidth = image.width
var isScrollLeftToRight = true
var currentX = 0
val handler = Handler()
val r = object : Runnable {
override fun run() {
// 右端まで表示したらスクロール方向を左へ変更する
if (drawableWidth < currentX + imageWidth) {
isScrollLeftToRight = false
}
if (currentX < 0) {
repeatCount++
isScrollLeftToRight = true
}
if (repeatCount == 2) return
val scrollX = getScrollX(isScrollLeftToRight)
currentX += scrollX
image.scrollBy(
scrollX,
0
)
handler.postDelayed(this, 10)
}
}
handler.post(r)
}
}
動かしてみました
美味しそうな寿司が動きました
カスタムビューで実装する
カスタムビューで実装する
activity_scroll_image_view.xml
<jp.co.yiwaisako.ui_sample.AutoHorizontalScrollImageView
android:id="@+id/sushi"
android:layout_width="200dp"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/sushi"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
カスタムビューで実装する
AutoHorizontalScrollImageView(1)
init {
scaleType = ScaleType.MATRIX
}
// スクロールを繰り返す上限回数
var maxRepeatCount = 1
// 1回のスクロール量
var scrollValueXForOneTime = 1
// スクロールした回数
private var repeatCount = 0
// 現在のX位置
private var currentX = 0
// 繰り返すかどうか
private val isAutoScroll: Boolean
get() {
return repeatCount < maxRepeatCount
}
// スクロール方向
private var direction: Direction = Direction.TO_RIGHT
// スクロール量
private val scrollValueX: Int
get() {
return when (direction) {
Direction.TO_RIGHT -> {
scrollValueXForOneTime
}
Direction.TO_LEFT -> {
-scrollValueXForOneTime
}
}
}
enum class Direction {
TO_RIGHT,
TO_LEFT
}
カスタムビューで実装する
AutoHorizontalScrollImageView(2)
override fun onDraw(canvas: Canvas?) {
if (isAutoScroll) {
scrollTo(scrollValueX)
// scrollTo()の後に実行してください
decideDirectionAfterScrolled()
}
super.onDraw(canvas)
}
private fun scrollTo(scrollValueX: Int) {
currentX += scrollValueX
scrollBy(scrollValueX, 0)
}
private fun decideDirectionAfterScrolled() {
if (currentX <= 0) {
repeatCount++
direction = Direction.TO_RIGHT
}
if (drawable.intrinsicWidth <= currentX + width) {
direction = Direction.TO_LEFT
}
}
サンプルレイアウトに配置
まとめ
- 水平方向の自動スクロールを実装しました
- リピート回数、スクロール量などの調整をDatabindingで対応しても良さそう(今回は未対応です)
- コードの
scrollTo()の後に実行してください
のコメントを無くしたい(メソッドの実行順番を利用者に意識させない)のですがよい修正案が思いつかなく、アドバイスありましたらお願いします。