我写了一个自定义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
虽然这感觉很hacky而且无法扩展。如果我决定让一个孩子成为另一种布局(例如,CustomListViewAdapter
),我将不得不提供另一个自定义类,或者理想的方法是通过接口找到一种方法。让我们说它不理想。
我真正想到的另一种方法是让CustomListView
向View
提供回调,当Adapter
滚动到或离开时,将会调用该回调。这实际上已经好一点了,但是我不确定它是否会破坏{{1}}的抽象。我很好奇是否还有其他方法我还没有考虑过。