Переписать
Мне не особо повезло с передачей действий прокрутки в одном ListView к другому. Поэтому я выбрал другой метод: прохождение MotionEvent
. Это позволяет каждому ListView
вычислять свою собственную плавную прокрутку, быструю прокрутку или что-либо еще.
Во-первых, нам понадобятся некоторые переменные класса:
ListView listView;
ListView listView2;
View clickSource;
View touchSource;
int offset = 0;
Каждый метод, который я добавлю в listView
, будет почти идентичен для listView2
, единственная разница что listView2
будет ссылаться на listView
(не на себя). Я не включил повторяющийся код listView2
.
Во-вторых, давайте начнем с OnTouchListener:
listView = (ListView) findViewById(R.id.engNameList);
listView.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(touchSource == null)
touchSource = v;
if(v == touchSource) {
listView2.dispatchTouchEvent(event);
if(event.getAction() == MotionEvent.ACTION_UP) {
clickSource = v;
touchSource = null;
}
}
return false;
}
});
Чтобы предотвратить циклическую логику: listView
вызовов listView2
вызовов listView
вызовов ... Я использовал класс переменная touchSource
, чтобы определить, когда должно быть передано MotionEvent
. Я предположил, что вы не хотите, чтобы щелчок строки в listView
также щелкал в listView2
, поэтому я использовал другую переменную класса clickSource
, чтобы предотвратить это.
В-третьих, OnItemClickListener:
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
if(parent == clickSource) {
// Do something with the ListView was clicked
}
}
});
В-четвертых, прохождение каждого события касания не является идеальным, поскольку появляются случайные расхождения. OnScrollListener идеально подходит для устранения этих проблем:
listView.setOnScrollListener(new OnScrollListener() {
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if(view == clickSource)
listView2.setSelectionFromTop(firstVisibleItem, view.getChildAt(0).getTop() + offset);
}
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {}
});
(Необязательно) Наконец, вы упомянули, что у вас возникли проблемы, поскольку listView
и listView2
начинаются на разных высотах в макете. Я настоятельно рекомендую изменить макет, чтобы сбалансировать ListViews, но я нашел способ решить эту проблему. Однако это немного сложно.
Вы не можете рассчитать разницу в высоте между двумя макетами до тех пор, пока не будет визуализирован весь макет, но для этого момента обратного вызова нет ... поэтому я использую простой обработчик:
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Set listView's x, y coordinates in loc[0], loc[1]
int[] loc = new int[2];
listView.getLocationInWindow(loc);
// Save listView's y and get listView2's coordinates
int firstY = loc[1];
listView2.getLocationInWindow(loc);
offset = firstY - loc[1];
//Log.v("Example", "offset: " + offset + " = " + firstY + " + " + loc[1]);
}
};
I предположим , что задержка в полсекунды достаточно велика для визуализации макета и запуска таймера в onResume()
:
handler.sendEmptyMessageDelayed(0, 500);
Если вы используете смещение, я хочу пояснить, что listView2
Метод OnScroll вычитает смещение, а не добавляет его:
listView2.setSelectionFromTop(firstVisibleItem, view.getChildAt(0).getTop() - offset);
Надеюсь, это поможет!
По умолчанию
и
(среди прочего) имеют связанные с ними поля и отступы. Попытка добавить следующее в свой CSS:
p, h2 {
margin: 0px;
padding: 0px;
}
Наличие отступов не повлияет на границу и фон элементов, но в зависимости от того, что вы хотите, вы можете попробовать удалить их, как это делаю я здесь.
Edit : как Гуффа указал в ответе ниже, причина того, что поля абзаца и заголовка выходят за пределы их контейнерных DIV, связана с сжимающимися полями.
Чтобы избежать подобных ситуаций, используйте что-то вроде YUI Reset . Он устанавливает CSS по умолчанию на что-то предсказуемое для всех браузеров.
Это из-за обрушивающихся полей . Поля - это не то, что окружает отдельный элемент, например отступы. Вместо этого маржа определяет расстояние между элементами. Если родительский элемент не имеет полей или отступов (например, элементы div в вашем коде), поля дочерних элементов (h2 и p) определяют расстояние между родительскими элементами, а не дочерними элементами.
На данный момент как правило, следует избегать сворачивания полей, когда у родительских элементов установлен фон, поскольку IE (по крайней мере, до версии 7) не обрабатывает сворачивающиеся поля правильно.
Если вы просто установите некоторые отступы в своих элементах div (это выглядит как вы должны иметь это в любом случае), поля не рухнут за их пределами.
Я (обычно) начинаю каждый файл CSS со следующего, чтобы не попасть в ловушку автоматического заполнения / полей:
*
{
margin-top: 0;
margin-right: 0;
margin-bottom: 0;
margin-left: 0;
padding-top: 0;
padding-right: 0;
padding-bottom: 0;
padding-left: 0;
}
редактировать для ясности:
*
{
margin: 0;
padding: 0;
}
делает то же самое.
Вы пробовали выполнить сброс css перед добавлением собственного CSS?
Проблема из-за схлопывающихся полей . Поля элементов h1 и p вносят вклад в поля основного блока div. Вы можете исправить это, удалив поля на этих элементах:
h1,p { margin: 0; }
или добавив границу или отступ к div:
#main { padding: 1px; }
Также убедитесь, что ваш HTML правильно сформирован, у вас есть случайный a >
в вашем примере.