Я реализовал некоторый код обнаружения жеста так, чтобы я мог обнаружить, когда строка в моем 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 с соответствующим дополнением высоты (так, чтобы это покрыло сильно ударенную строку).
Любая справка очень ценилась бы!
Существует два различных способа индексации элементов 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);
Я решил эту проблему, но это похоже на взлом и, вероятно, не самая эффективная реализация. Наверняка должен существовать более чистый способ сделать это с помощью 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);
}
}