Как получить местоположение (на экране) строки в listview

Я реализовал некоторый код обнаружения жеста так, чтобы я мог обнаружить, когда строка в моем listview (который расположен в FrameLayout) была сильно ударена.

public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
        int itemId = MainActivity.this.getListView().pointToPosition((int) e1.getX(),(int) e1.getY());
        Offer order = (Offer)MainActivity.this.getListView().getAdapter().getItem(itemId);
        View v = MainActivity.this.getListView().getChildAt(itemId);
    }
}

Я хочу отобразить представление поверх сильно ударенной строки с рядом контекстно-зависимых опций для той строки.

Мои проблемы состоят в том что следующие методы:

v.getTop()
v.getBottom()

возвратите правильные значения только, прежде чем представление было прокручено. Я мог, вероятно, сделать некоторое вычисление для разработки смещений с помощью положений прокрутки и т.д., но я также заметил, что только получаю значения, когда я сильно ударяю строку, которая видима на экране для начала. Если я прокручиваю список вниз и затем сильно ударяю строку (который не был первоначально внеэкранным), затем, эти методы возвращают нулевые значения.

Методы ниже, кажется, страдают от той же проблемы...

v.getLocationOnScreen(loc)
v.getLocationInWindow(loc)

В конечном счете я надеюсь находить расстояние между вершиной видимого listView и строкой, которая была сильно ударена. Я буду затем использовать это расстояние, чтобы добавить представление к родительскому FrameLayout с соответствующим дополнением высоты (так, чтобы это покрыло сильно ударенную строку).

Любая справка очень ценилась бы!

7
задан Damian 26 January 2010 в 20:08
поделиться

2 ответа

Существует два различных способа индексации элементов ListView, по позиции в адаптере или видимым местом на экране. Предмет всегда будет в том же положении в адаптере (если вы не измените список). Индекс в View.getChildat () будет варьироваться в зависимости от того, что видно на экране.

Должность, возвращаемая PointToStoStion, является положение в пределах адаптера. Если вы хотите получить физический вид, вам нужно учитывать, если вид прокручивается. Попробуйте это:

int adapterIndex = MainActivity.this.getListView().pointToPosition((int) e1.getX(),(int) e1.getY());
int firstViewItemIndex = MainActivity.this.getListView().getFirstVisiblePosition();
int viewIndex = adapterIndex - firstViewItemIndex;
View v = MainActivity.this.getListView().getChildAt(viewIndex);
17
ответ дан 6 December 2019 в 10:00
поделиться

Я решил эту проблему, но это похоже на взлом и, вероятно, не самая эффективная реализация. Наверняка должен существовать более чистый способ сделать это с помощью API Android?

В приведенном ниже коде я добавил HashMap в свой ArrayAdaptor, чтобы отслеживать, какие из представлений на экране содержат какие строки (поскольку они перерабатываются по мере того, как вы прокрутите список)

Все изменения, которые я внес в свой оригинальный адаптер, прокомментированы ниже.

 class RestaurantAdapter extends ArrayAdapter<Offer> {
            Map hash = null;  //HashMap to keep track of rowId and on screen View

            RestaurantAdapter() {
                super(MainActivity.this, android.R.layout.simple_list_item_1, model);
                hash = new HashMap(); //instantiate HashMap in constructor
            }

             //method to return correct View on screen for row id
            public View getViewOnScreen(int rowId) {
                return (View)hash.get(rowId);
            }

            public View getView(int position, View convertView,
                                                    ViewGroup parent) {
                View row=convertView;
                hash.put(position, convertView); // add/update view for row position as it is recycled 

                RestaurantWrapper wrapper=null;

                if (row==null) {                                                    
                    LayoutInflater inflater=getLayoutInflater();

                    row=inflater.inflate(R.layout.row, parent, false);
                    wrapper=new RestaurantWrapper(row);
                    row.setTag(wrapper);
                }
                else {
                    wrapper=(RestaurantWrapper)row.getTag();
                }

                wrapper.populateFrom(model.get(position));

                return(row);
            }


        }
1
ответ дан 6 December 2019 в 10:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: