#android
#Android
Вопрос:
Я написал пользовательский View
, давайте назовем его CustomListView
который расширяет LinearLayout
. CustomListView
Использует Adapter
для создания своих дочерних элементов. Я также реализовал поведение, при котором дочерний элемент отображается по-другому, когда он расположен определенным образом — например, когда вы прокручиваете список, фон дочернего элемента, который в данный момент виден вверху списка, становится прозрачным. Так, например:
Запуск:
-----------------------------
| child 1 (transparent bg) |
-----------------------------
| child 2 (visible) |
-----------------------------
| child 3 (visible) |
-----------------------------
| child 4 (visible) |
-----------------------------
| child 5 (visible) |
-----------------------------
| child 6 (visible) |
-----------------------------
После прокрутки вниз до того места, где дочерний элемент 3 находится вверху списка:
-----------------------------
| child 3 (transparent bg) |
-----------------------------
| child 4 (visible) |
-----------------------------
| child 5 (visible) |
-----------------------------
| child 6 (visible) |
-----------------------------
| child 7 (visible) |
-----------------------------
| child 8 (visible) |
-----------------------------
Проблема в том, что я не очень доволен тем, как я этого добился. На данный момент я делаю это, создавая пользовательский View
, CustomListViewChild
который наследуется от RelativeLayout
и который я использую в качестве корневого представления для каждого дочернего элемента. Это важная часть реализации CustomListViewChild
:
public final class CustomListViewChild extends RelativeLayout {
private OnScrolledToListener onScrolledToListener;
private OnScrolledFromListener onScrolledFromListener;
/**
* Called when this {@link CustomListViewChild} has been scrolled to (i.e. it is now at the top of the
* {@link CustomListView})
*/
public void scrollTo() {
if (onScrolledToListener != null) {
onScrolledToListener.onScrolledTo();
}
}
/**
* Called when this {@link CustomListViewChild} has been scrolled from (i.e. it is no longer at the
* top of the {@link CustomListView})
*/
public void scrollFrom() {
if (onScrolledFromListener != null) {
onScrolledFromListener.onScrolledFrom();
}
}
/**
* @param onScrolledToCallback a listener to be called when this {@link CustomListViewChild} is
* scrolled to (i.e. the scroll of the {@link CustomListView} has come to an end with this
* {@link CustomListViewChild} at the top).
*/
public void setOnScrolledToListener(OnScrolledToListener onScrolledToCallback) {
this.onScrolledToListener = onScrolledToCallback;
}
/**
* @param onScrolledFromCallback a listener to be called when this view is scrolled away from
* (i.e. this was previously the top {@link CustomListViewChild} in the {@link CustomListView}
* but now the user has scrolled away from it.)
*/
public void setOnScrolledFromListener(OnScrolledFromListener onScrolledFromCallback) {
this.onScrolledFromListener = onScrolledFromCallback;
}
/**
* An interface used to listen for when this {@link CustomListViewChild} has been scrolled to.
*/
public interface OnScrolledToListener {
/**
* Method called when this {@link CustomListViewChild} has been scrolled to.
*/
void onScrolledTo();
}
/**
* An interface used to listen for when this {@link CustomListViewChild} has been scrolled from.
*/
public interface OnScrolledFromListener {
/**
* Method called when this {@link CustomListViewChild} has been scrolled from.
*/
void onScrolledFrom();
}
}
Затем, в моем Adapter
:
if (convertView instanceof CustomListViewChild) {
((CustomListViewChild) convertView).setOnScrolledFromListener(new OnScrolledFromListener() {
@Override
public void onScrolledFrom() {
viewHolder.screenshot.setVisibility(View.VISIBLE);
}
});
((CustomListViewChild) convertView).setOnScrolledToListener(new OnScrolledToListener() {
@Override
public void onScrolledTo() {
viewHolder.screenshot.setVisibility(View.GONE);
}
});
}
Хотя это кажется хакерским и не расширяемым. Если я когда-нибудь решу завести дочерний элемент с другим типом макета (скажем, LinearLayout
), мне пришлось бы предоставить другой пользовательский класс или, в идеале, придумать способ сделать это с помощью интерфейса… давайте просто скажем, что это не идеально.
Другой подход, о котором я буквально только что подумал, заключается в том, что я CustomListViewAdapter
предоставляю обратные вызовы для CustomListView
, которые будут вызываться при View
прокрутке к или от. На самом деле это уже кажется немного лучше, но я не уверен, нарушает ли это Adapter
s абстракцию. Мне любопытно, есть ли какие-либо другие подходы, которые я не рассматривал.