GridView与baseAdapter:onItemClick给出错误的位置

时间:2011-08-30 04:56:36

标签: android gridview

我对GridView有一个奇怪的问题。

onItemClick(AdapterView父级,View v,int位置,长ID)

方法有时会给出错误的立场。 我的代码:

public class ImageAdapter extends BaseAdapter {
......
}

gridview = (GridView) findViewById(R.id.gridview);

image_adapter = new ImageAdapter(this);

gridview.setAdapter(image_adapter);

gridview.setOnItemClickListener(new OnItemClickListener() {

            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
                Log.e(TAG, "position = "+position);
                       }
  }

我的gridView是3X3网格,图像适配器有9个图像。根据用户选择的网格位置,图像片段会被洗牌。

如果选择网格位置缓慢,这可以正常工作。但是如果用户继续在任何特定位置快速点击,onItemClick方法中的“position”参数会被任意改变。 假设我的网格是

0  1  2

3  4  5

6  7  8

并且用户继续在第5位快速点击,有时onItemClick中的“position”参数读取0或6。

任何想法是什么原因以及解决方案是什么?

5 个答案:

答案 0 :(得分:2)

我的项目遇到了同样的麻烦 - 也许它会帮助你。

您可能在Activity中有onTouchEvent的实现。做到这样:

@Override
    public boolean onTouch(View v, MotionEvent event) {
        // TODO Auto-generated method stub
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            startX = event.getX();//probably Click
            return false;
        case MotionEvent.ACTION_UP:
            float currentX = event.getX();
            if (this.startX-MOVE_DENSITY > currentX) {
                //fling right
                            return true;
            }
            if (this.startX+MOVE_DENSITY < currentX) {
                //fling left
                return true;
            }
            default:
            return false;
        }   
    }

返回值非常重要!!!你必须在你的类中有一个字段double startX,并且常量MOVE_DENSITY,这意味着密度来检测fling移动(在我的例子中,我将它设置为50)。也许不是很好的解释,但我的英语不太好))希望它对你有帮助!

答案 1 :(得分:1)

出现同样的问题,以下问题解决了这个问题:

grid.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
           int position = i - grid.getNumColumns();
        }
});

我正在使用HeaderGridView类: https://android.googlesource.com/platform/packages/apps/Gallery2/+/idea133/src/com/android/photos/views/HeaderGridView.java

答案 2 :(得分:0)

而不是OnItemClickListener,您最好使用OnItemSelectedListener

答案 3 :(得分:0)

我遇到了类似这样的问题。我不知道您是否设置了gridview.setEnabled truefalse,但我做到了。如果用户在gridview.setEnabled触发器之前和之下点击疯狂的项目,则gridview有时会使你的位置错误。

为了解决这个问题,我在网格视图的顶部创建了一个透明的RelativeLayout,我将其设置为可见。 RelativeLayout必须为android:clickable="true"

答案 4 :(得分:0)

根据Viacheslav的回答,我做了一些修改。

在我自己的班级(Customized GridView)中:

public class CustomGridView extends GridView {
    private int position = -1;
    private float xCoor, yCoor;
    private Context context;
    private Drawable defaultDrawable;
    //Constructors - Skipped
    public void setInitPosition(int position, float x, float y) {
        this.position = position;
        this.xCoor = x;
        this.yCoor = y;
        defaultDrawable = this.getChildAt(position - this.getFirstVisiblePosition()).getBackground();
        this.getChildAt(position - this.getFirstVisiblePosition()).setBackgroundColor(Color.RED/*For Example*/));
    }

    @Override
    public boolean performClick() {
        return super.performClick();
    }

    public int getInitialPosition() {
        if(position != -1) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                this.getChildAt(position - this.getFirstVisiblePosition()).setBackground(defaultDrawable);
            } else {
                this.getChildAt(position - this.getFirstVisiblePosition()).setBackgroundColor(context.getResources().getColor(R.color.grid_selection_item_background));
            }
        }
        return position;
    }
    public float xCoor() {
        return xCoor;
    }

    public float yCoor() {
        return yCoor;
    }
}

在你的onTouchListener中:

CustomGridView gridView;
...    

@Override
public boolean onTouch(View v, MotionEvent event) {
    v.performClick();
    int action = event.getActionMasked();
    float xPosition = event.getX();
    float yPosition = event.getY();
    int position = listView.pointToPosition((int) xPosition, (int) yPosition);
    if(position != AbsListView.INVALID_POSITION) {
        if(action == MotionEvent.ACTION_DOWN) {
            gridView.setInitialPosition(position, xPosition, yPosition);
        }
        if(action == MotionEvent.ACTION_UP) {
            int checkedPosition = gridView.getInitialPosition();
            if(checkedPosition == position) {
                if(Math.abs(yPosition - gridView.yCoor()) < 10/*Your fling "density"*/) {
                    doYourAction(position);
                }
            }
        }
    }
    return detector.onTouchEvent(event);
}

onTouch Callback中的位置是gridView中项目的位置,而不是视图位置。查看位置必须使用gridView.getFirstVisiblePosition()

扣除