GridView с baseAdapter: onItemClick дает неправильную позицию - PullRequest
1 голос
/ 30 августа 2011

У меня странная проблема с GridView.

onItemClick (родительский элемент AdapterView, View v, int position, long 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 изображений. В зависимости от того, какую позицию сетки выбирает пользователь, части изображения перетасовываются.

Это прекрасно работает, если выбор позиции сетки выполняется медленно. Но если пользователь продолжает очень быстро нажимать на какую-либо конкретную позицию, параметр «position» в методе onItemClick изменяется произвольно. Предположим, что моя сетка

0  1  2

3  4  5

6  7  8

и пользователь продолжает быстрым шагом нажимать на позицию 5, иногда параметр "position" в onItemClick читает 0 или 6.

Есть идеи, в чем причина этого и какое может быть решение?

Ответы [ 5 ]

2 голосов
/ 12 ноября 2011

У меня такая же проблема в моем проекте - возможно, это поможет вам.

Возможно, у вас есть реализация 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, что означает плотность для определения движения броска (в моем случае я установил его на 50).Может быть, не хорошее объяснение, но мой английский не очень хорошо)) Надеюсь, это поможет вам!

1 голос
/ 23 января 2017

Если бы возникла та же проблема, проблема была решена следующим образом:

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

0 голосов
/ 14 декабря 2017

На основании ответа Вячеслава я внес некоторые изменения.

В моем собственном классе (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 - это позиция элемента в gridView, а не позиция просмотра. Позиция просмотра должна быть вычтена с gridView.getFirstVisiblePosition()

0 голосов
/ 03 февраля 2015

У меня была такая проблема. Я не знаю, если вы установили gridview.setEnabled true и false, но я сделал. Если пользователь нажимает на элемент, как сумасшедший, непосредственно перед триггерами gridview.setEnabled и под ним, то gridview иногда может дать вам неправильную позицию.

Чтобы решить эту проблему, я сделал прозрачный RelativeLayout поверх сетки, который я установил как пропущенный и видимый. RelativeLayout должен быть android:clickable="true".

0 голосов
/ 30 августа 2011

Вместо OnItemClickListener лучше использовать OnItemSelectedListener

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...