问题
I am trying to make a fake horizontal ListView. For that, I want to rotate the content of each cell in the adapter. It almost works:
class ImageAdapter(ctx: Context, viewResourceId: Int, imageResourceId: Int, strings: Array[String], icons: TypedArray, colorSelected: Int, colorNotSelected: Int, colorBorder: Int) extends ArrayAdapter[String](ctx, viewResourceId, strings) {
// Useful variables
private val mInflater: LayoutInflater = ctx.getSystemService(
Context.LAYOUT_INFLATER_SERVICE).asInstanceOf[LayoutInflater]
private val mStrings: Array[String] = strings
private val mIcons: TypedArray = icons
private val mViewResourceId: Int = viewResourceId
private var mSelected : Int = 0
def setSelected(s: Int) = mSelected = s
// Inherited from ArrayAdapter
override def getCount():Int = mStrings.length
override def getItem(position: Int): String = mStrings(position)
override def getItemId(position: Int): Long = position
// The rotation machinery
var rotation = 90
private var matrix = new Matrix()
val rect1 = new RectF(0, 0, 0, 0)
val rect2 = new RectF(0, 0, 0, 0)
val cst = Matrix.ScaleToFit.CENTER
// Getting the view.
override def getView(position: Int, convertView: View, parent: ViewGroup): View = {
var result = if(convertView == null) mInflater.inflate(mViewResourceId, null) else convertView
var iv: ImageView = result.findViewById(imageResourceId).asInstanceOf[ImageView]
val drawable = mIcons.getDrawable(position)
iv.setScaleType(ScaleType.MATRIX)
matrix.reset()
val height = drawable.getIntrinsicHeight()
val width = drawable.getIntrinsicWidth()
rotation match {
case 0 =>
rect1.set(0, 0, width, height)
rect2.set(0, 0, iv.getWidth(), iv.getHeight())
matrix.setRectToRect(rect1, rect2, cst)
case 90 =>
rect1.set(0, 0, width, height)
rect2.set(-iv.getHeight()/2, -iv.getWidth()/2, iv.getHeight()/2, iv.getWidth()/2)
matrix.setRectToRect(rect1, rect2, cst)
matrix.postRotate(rotation, 0, 0)
matrix.postTranslate(iv.getWidth()/2, iv.getHeight()/2)
...
case _ =>
}
iv.setImageMatrix(matrix)
iv.setImageDrawable(drawable)
iv.postInvalidate()
if(position == mSelected) {
result.setBackgroundColor(colorSelected)
} else {
result.setBackgroundColor(colorNotSelected)
}
result.setTag(mStrings(position))
result
}
}
The only problem is that it does not display the first picture. Instead, it displays this:
For the first list to appear, I need to click on one element of each list. The onclick method is the following:
listGraphismesView.setOnItemClickListener(new OnItemClickListener {
override def onItemClick(parent: AdapterView[_], view: View, position: Int, notUsedId: Long) = {
var graphismeName = view.getTag().asInstanceOf[String]
mAdapter.setSelected(position)
mAdapter.notifyDataSetChanged()
showGChallenge(position, graphismeName)
}
})
I tried then to put mAdapter.notifyDataSetChanged() in the onResume function of the fragment, but it does not update the list from the beginning. I still need to click on something for all images to appear. Any idea why ?
回答1:
I found out that iv.getWidth() and iv.getHeight() were both returning zero because the getview would be called by the onActivityCreated function. Putting notifyDataSetChanged() in the onResume function was too early too. So the drawable would be drawn with size 0, and reloaded when I could click on the button.
So to change that, I wrote the following piece of code, calling the resize function with a listener.
var iv: ImageView = result.findViewById(imageResourceId).asInstanceOf[ImageView]
val drawable = mIcons.getDrawable(position)
iv.setImageDrawable(drawable)
iv.setScaleType(ScaleType.MATRIX)
val vto = iv.getViewTreeObserver()
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
private var matrix = new Matrix()
val rect1 = new RectF(0, 0, 0, 0)
val rect2 = new RectF(0, 0, 0, 0)
private var height = drawable.getIntrinsicHeight()
private var width = drawable.getIntrinsicWidth()
override def onGlobalLayout() {
val iv_width = iv.getWidth
val iv_height = iv.getHeight
matrix.reset()
rotation match {
case 0 =>
rect1.set(0, 0, width, height)
rect2.set(0, 0, iv_width, iv_height)
matrix.setRectToRect(rect1, rect2, cst)
case 90 =>
rect1.set(0, 0, width, height)
rect2.set(-iv_height/2, -iv_width/2, iv_height/2, iv_width/2)
matrix.setRectToRect(rect1, rect2, cst)
matrix.postRotate(rotation, 0, 0)
matrix.postTranslate(iv_width/2, iv_height/2)
...
case _ =>
}
iv.setImageMatrix(matrix)
}
})
来源:https://stackoverflow.com/questions/15593152/rotating-images-in-listview