はじめに
こんな記事を書いておいてなんですが、まず大前提として取得してくる画像のサイズを揃えることを検討するべきだとは思います。
それでも**「不揃いな画像を取得してきて、縦横それぞれ等しくN倍したwrap_contentなImageViewを並べたい」**という謎の機能要件が有ったのでこの記事を書くに至りました。
今回使った主なライブラリのバージョンは下記です、適宜読み替えて下さい。
- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61
- com.squareup.picasso:picasso:2.71828
概要
画像の拡大はImageViewのscaleTypeをゴニョゴニョするという認識でしたが、まずImageViewのサイズを絶対値ないしmatch_parentに固定せねばなりません。
例えば取得してくる画像のサイズがそれぞれ
- 100 × 160
- 150 × 180
- 200 × 120
のように全てバラバラだったとき、先にImageViewのサイズを決めてしまうことにより
- 予め決めた範囲内での画像の拡大になってしまう
- よしんばN倍出来ても、それらを並べたときに上下左右に無用なスペースが生まれてしまうことがある
という問題が発生してしまいました。
例で上げた3枚の画像を縦横それぞれ2倍するとしたら、下記のようなサイズになるはずです。
- 100 × 160 => 200 × 320
- 150 × 180 => 300 × 360
- 200 × 120 => 400 × 240
実装
PicassoのTransformationインターフェースを実装する形で解決出来ました。
class ScaleTransformation(
private val scale: Float
) : Transformation {
override fun transform(source: Bitmap?): Bitmap? {
source ?: return null
//1倍にするとcreateBitmapしてもsourceを返そうとして死ぬ
if (scale == 1f) {
return source
}
val matrix = Matrix().apply {
setScale(
scale,
scale
)
}
val result = Bitmap.createBitmap(
source,
0,
0,
source.width,
source.height,
matrix,
true
)
source.recycle()
return result
}
override fun key(): String =
"ScaleTransformation(scale = $scale)"
}
Picassoで画像をloadする際に、倍率をFloatで指定してセットしてあげれば動きます。
Picasso.get()
.load(imageUrl)
.transform(ScaleTransformation(2f)) //← 倍率を指定
.into(image_view)
終わりに
もともとの画像サイズがバラバラとは言えど、ある程度常識的な範囲に収まるという前提のコードになっています。
元画像のサイズがとてつもなく巨大なときなどに画像を拡大しようとするとメモリリーク不可避な感じになる気がするので、ちゃんとやるなら変換後の画像サイズに応じて、入力された等倍の割合をよしなに緩めるなどの対応が必要かと思います。