Android:在 Adapter 中发生触摸事件时更新 GridView 中的图像
Android : Update Image in GridView on touch event in Adapter
我有一个 GridView
并附有适配器。适配器填充网格中的图像。我在 Activity
中将 setOnTouchLister
设置为 GridView
并仅在适配器中实现。在适配器中,我有一个 Integer[] imageIDs
,其中包含添加的所有图像的资源 ID 和一个扩展 ImageView
并设置了其他属性的 ArrayList<ImageSourceObject> imgObjsArr
。
现在onTouch()
,我想把选中图片的图片换成其他图片。这是我的代码:
在 onCreate
中设置 Activity
中的网格适配器:
// Set Objects in Game View
gameView = (GridView) this.findViewById(R.id.game_gridView);
gameObjAdapter = new GameObjectsAdapter(this, R.id.game_gridView, null);
gameView.setAdapter(gameObjAdapter);
适配器:
public class GameObjectsAdapter extends BaseAdapter implements OnTouchListener {
super();
mContext = c;
this.layoutResourceId = layoutResourceId;
objects = data;
gridViewResAdap = (GridView) mContext.findViewById(this.layoutResourceId);
createObjectsArray();
Log.d("GOA", "Created Objects Array");
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageSourceObject imgView;
if (convertView == null) {
imgView = new ImageSourceObject(mContext);
imgView.setLayoutParams(new GridView.LayoutParams(20, 20));
imgView.getScaleType();
imgView.setScaleType(ScaleType.FIT_XY);
imgView.setPadding(0, 0, 0, 0);
} else {
imgView = (ImageSourceObject) convertView;
}
// Chk status of touched of imgView & set image accordingly
if (imgView.isTouched())
imgView.setImage(R.drawable.droid_touched2);
else
imgView.setImage(imageIds[position]);
return imgView;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getActionMasked();
float currentXPos = event.getX();
float currentYPos = event.getY();
int position = gridViewResAdap.pointToPosition((int)currentXPos, (int) currentYPos);
// Key was Pressed Here
if (action == MotionEvent.ACTION_UP) {
if (position > 0) {
// Get the object which is clicked
ImageSourceObject isb = this.imgObjsArr.get(position);
Log.d("GA", " Postion ID " + isb.getId() + " [] ID : " + imageIds[position]);
// Change the status of touched & set image
isb.setTouched(true);
isb.setImage(R.drawable.droid_touched2);
// Update the ArrayList & Integer[] with this updated obj
this.imgObjsArr.set(position, isb);
imageIds[position] = R.drawable.droid_touched2;
Log.d("ISB", "++++ Object ID : " + isb.getId() + " [] ID : " + imageIds[position] + " ISB Touched :" + isb.isTouched());
Toast.makeText(mContext, "Postion Pressed : " + (position+1),
Toast.LENGTH_SHORT).show();
//this.gridViewResAdap.invalidate();
}
return true;
}
return false;
}
日志:
02-19 15:19:11.615: D/GA(2046): Postion ID 2130837556 [] ID : 2130837556
02-19 15:19:11.617: D/ISB(2046): ++++ Object ID : 2130837559 [] ID : 2130837559 ISB Touched :true
日志显示 Integer[]
和 ArrayList
中的对象都已更新并且具有正确的值。毕竟,图像也不会在屏幕上更新。 gridViewResAdap
也是从activity传来的grid对象。我也尝试在其上调用 invalidate()
,但没有结果。与我的 getView()
一样,我使用的是 imageIDs
,所以我也一直在更新它。
ImageSourceObject :
public class ImageSourceObject extends ImageView {
public void setImage(int resourceId) {
super.setImageResource(resourceId);
this.setId(resourceId);
}
此外,onTouch()
调用 onPerformClick()
时出错,我不确定在哪里调用以及为什么调用。我还没有在适配器中实现 onClickListener
。在 onTouch()
.
中处理事情时,在这种情况下可以做什么以及在 onClickListener
中写什么
你能帮我知道为什么图像对象没有更新吗?我哪里出错了?我以为我必须刷新网格,所以也调用了 invalidate(),但没有结果。
非常感谢任何帮助。
谢谢
你可以简单地做:
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getActionMasked();
float currentXPos = event.getX();
float currentYPos = event.getY();
int position = gridViewResAdap.pointToPosition((int)currentXPos, (int) currentYPos);
// Key was Pressed Here
if (action == MotionEvent.ACTION_UP) {
if (position > 0) {
((ImageView)v).setImageDrawable(ctx.getResources().getDrawable(R.drawable.droid_touched2));
}
return true;
}
return false;
}
在您的 ImageView
开始处理 TouchEvent 之后,它是唯一允许对该触摸手势执行任何操作的视图。您希望 GridView
拦截 TouchEvent,检查 TouchEvent (event.getX(); event.getY()
) 的 X 和 Y 坐标,并查看这些坐标是否落在您的 ImageView
对象之一的范围内。如果是,请在 ImageView
上设置一个标志或可以触发您的 setImageDrawable()
方法的东西。我能够在我的一个项目中实现类似的效果,但我必须创建一个自定义 GridView class (public class yourGridView extends GridView
),然后覆盖以下内容:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
Log.i(AGL, "InterceptAction = DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i(AGL, "InterceptAction = MOVE");
break;
case MotionEvent.ACTION_CANCEL:
Log.i(AGL, "InterceptAction = CANCEL");
return false;
}
return true; //returning true tells your main Activity that you want the custom GridView to handle this TouchEvent; It will then send the TouchEvent to your GridView's onTouchEvent() method for handling.
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_MOVE:
int xCoord = (int) event.getX();
int yCoord = (int) event.getY();
Log.i(AGL, "MOVE EVENT;" + "\n" + "Touch X = " + Integer.toString(xCoord) + "\n" +
"Touch Y = " + Integer.toString(yCoord));
for(int i = 0; i < this.getChildCount(); i++) {
ImageView suspect = (ImageView) this.getChildAt(i);
if(suspect.getBounds().contains(xCoord, yCoord)) {
suspect.CHANGE_YOUR_IMAGE_HERE();
suspect.invalidate();
}
}
break;
}
return true;
}
请注意:getBounds() 是我在自定义 ImageView
class 中编写的方法。此方法 returns 表示 ImageView
对象边界框的 Rect 对象。您将不得不使用自己的逻辑来获取 ImageView
.
的边界
另请注意:当我 运行 在我的项目中使用此逻辑时,我的 ImageView
会在触摸手势期间快速更改图像。我还没有想出如何将它限制为每个 MotionEvent.ACTION_MOVE.
一个图像更改
希望对您有所帮助。
我有一个 GridView
并附有适配器。适配器填充网格中的图像。我在 Activity
中将 setOnTouchLister
设置为 GridView
并仅在适配器中实现。在适配器中,我有一个 Integer[] imageIDs
,其中包含添加的所有图像的资源 ID 和一个扩展 ImageView
并设置了其他属性的 ArrayList<ImageSourceObject> imgObjsArr
。
现在onTouch()
,我想把选中图片的图片换成其他图片。这是我的代码:
在 onCreate
中设置 Activity
中的网格适配器:
// Set Objects in Game View
gameView = (GridView) this.findViewById(R.id.game_gridView);
gameObjAdapter = new GameObjectsAdapter(this, R.id.game_gridView, null);
gameView.setAdapter(gameObjAdapter);
适配器:
public class GameObjectsAdapter extends BaseAdapter implements OnTouchListener {
super();
mContext = c;
this.layoutResourceId = layoutResourceId;
objects = data;
gridViewResAdap = (GridView) mContext.findViewById(this.layoutResourceId);
createObjectsArray();
Log.d("GOA", "Created Objects Array");
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageSourceObject imgView;
if (convertView == null) {
imgView = new ImageSourceObject(mContext);
imgView.setLayoutParams(new GridView.LayoutParams(20, 20));
imgView.getScaleType();
imgView.setScaleType(ScaleType.FIT_XY);
imgView.setPadding(0, 0, 0, 0);
} else {
imgView = (ImageSourceObject) convertView;
}
// Chk status of touched of imgView & set image accordingly
if (imgView.isTouched())
imgView.setImage(R.drawable.droid_touched2);
else
imgView.setImage(imageIds[position]);
return imgView;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getActionMasked();
float currentXPos = event.getX();
float currentYPos = event.getY();
int position = gridViewResAdap.pointToPosition((int)currentXPos, (int) currentYPos);
// Key was Pressed Here
if (action == MotionEvent.ACTION_UP) {
if (position > 0) {
// Get the object which is clicked
ImageSourceObject isb = this.imgObjsArr.get(position);
Log.d("GA", " Postion ID " + isb.getId() + " [] ID : " + imageIds[position]);
// Change the status of touched & set image
isb.setTouched(true);
isb.setImage(R.drawable.droid_touched2);
// Update the ArrayList & Integer[] with this updated obj
this.imgObjsArr.set(position, isb);
imageIds[position] = R.drawable.droid_touched2;
Log.d("ISB", "++++ Object ID : " + isb.getId() + " [] ID : " + imageIds[position] + " ISB Touched :" + isb.isTouched());
Toast.makeText(mContext, "Postion Pressed : " + (position+1),
Toast.LENGTH_SHORT).show();
//this.gridViewResAdap.invalidate();
}
return true;
}
return false;
}
日志:
02-19 15:19:11.615: D/GA(2046): Postion ID 2130837556 [] ID : 2130837556
02-19 15:19:11.617: D/ISB(2046): ++++ Object ID : 2130837559 [] ID : 2130837559 ISB Touched :true
日志显示 Integer[]
和 ArrayList
中的对象都已更新并且具有正确的值。毕竟,图像也不会在屏幕上更新。 gridViewResAdap
也是从activity传来的grid对象。我也尝试在其上调用 invalidate()
,但没有结果。与我的 getView()
一样,我使用的是 imageIDs
,所以我也一直在更新它。
ImageSourceObject :
public class ImageSourceObject extends ImageView {
public void setImage(int resourceId) {
super.setImageResource(resourceId);
this.setId(resourceId);
}
此外,onTouch()
调用 onPerformClick()
时出错,我不确定在哪里调用以及为什么调用。我还没有在适配器中实现 onClickListener
。在 onTouch()
.
onClickListener
中写什么
你能帮我知道为什么图像对象没有更新吗?我哪里出错了?我以为我必须刷新网格,所以也调用了 invalidate(),但没有结果。
非常感谢任何帮助。
谢谢
你可以简单地做:
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getActionMasked();
float currentXPos = event.getX();
float currentYPos = event.getY();
int position = gridViewResAdap.pointToPosition((int)currentXPos, (int) currentYPos);
// Key was Pressed Here
if (action == MotionEvent.ACTION_UP) {
if (position > 0) {
((ImageView)v).setImageDrawable(ctx.getResources().getDrawable(R.drawable.droid_touched2));
}
return true;
}
return false;
}
在您的 ImageView
开始处理 TouchEvent 之后,它是唯一允许对该触摸手势执行任何操作的视图。您希望 GridView
拦截 TouchEvent,检查 TouchEvent (event.getX(); event.getY()
) 的 X 和 Y 坐标,并查看这些坐标是否落在您的 ImageView
对象之一的范围内。如果是,请在 ImageView
上设置一个标志或可以触发您的 setImageDrawable()
方法的东西。我能够在我的一个项目中实现类似的效果,但我必须创建一个自定义 GridView class (public class yourGridView extends GridView
),然后覆盖以下内容:
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_DOWN:
Log.i(AGL, "InterceptAction = DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.i(AGL, "InterceptAction = MOVE");
break;
case MotionEvent.ACTION_CANCEL:
Log.i(AGL, "InterceptAction = CANCEL");
return false;
}
return true; //returning true tells your main Activity that you want the custom GridView to handle this TouchEvent; It will then send the TouchEvent to your GridView's onTouchEvent() method for handling.
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
switch(action) {
case MotionEvent.ACTION_MOVE:
int xCoord = (int) event.getX();
int yCoord = (int) event.getY();
Log.i(AGL, "MOVE EVENT;" + "\n" + "Touch X = " + Integer.toString(xCoord) + "\n" +
"Touch Y = " + Integer.toString(yCoord));
for(int i = 0; i < this.getChildCount(); i++) {
ImageView suspect = (ImageView) this.getChildAt(i);
if(suspect.getBounds().contains(xCoord, yCoord)) {
suspect.CHANGE_YOUR_IMAGE_HERE();
suspect.invalidate();
}
}
break;
}
return true;
}
请注意:getBounds() 是我在自定义 ImageView
class 中编写的方法。此方法 returns 表示 ImageView
对象边界框的 Rect 对象。您将不得不使用自己的逻辑来获取 ImageView
.
另请注意:当我 运行 在我的项目中使用此逻辑时,我的 ImageView
会在触摸手势期间快速更改图像。我还没有想出如何将它限制为每个 MotionEvent.ACTION_MOVE.
希望对您有所帮助。