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.

一个图像更改

希望对您有所帮助。