J'essaie de détecter le défilement d'un affichage de liste au-delà d'un certain seuil en pixels (au milieu du premier élément) Malheureusement, getScrollY () de listview semble toujours renvoyer 0 instad de la position de défilement. Existe-t-il un moyen d'obtenir l'emplacement de défilement réel par pixel?
Voici le code que j'ai essayé d'utiliser mais comme dit, il ne retourne que 0.
getListView().setOnScrollListener(new AbsListView.OnScrollListener() {
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
Log.d("scroll", "scroll: " + getListView().getScrollY());
}
public void onScrollStateChanged(AbsListView view, int scrollState) {
if (scrollState == 0)
Log.d("scroll", "scrolling stopped");
}
});
Il n'y a aucune notion de défilement Y pour un ListView dans Android simplement parce que la hauteur totale du contenu est inconnue. Seule la hauteur du contenu affiché est connue.
Cependant, il est possible d'obtenir la position actuelle/défilement Y d'un élément visible en utilisant le hack suivant:
getListView().getChildAt(0).getTop();
Peut-être que ce sera utile pour quelqu'un. Le code des réponses précédentes ne fonctionnera pas si la liste défile rapidement. Parce que dans ce cas, firstVisiblePosition peut être modifié irrégulièrement. Dans mon code, je n'utilise pas de tableau pour stocker des positions
fun setOnTouchScrollListener(lv: AbsListView, onTouchScrollListener: (isDown: Boolean, offset: Int?, isScrollWorking: Boolean) -> Unit) {
var lastItemPosition: Int = -1
var lastItemTop: Int? = null
var lastItemHeight: Int? = null
var lastScrollState: Int? = AbsListView.OnScrollListener.SCROLL_STATE_IDLE
lv.setOnScrollListener(object : AbsListView.OnScrollListener {
override fun onScroll(view: AbsListView, firstVisibleItem: Int, visibleItemCount: Int, totalItemCount: Int) {
val child = lv.getChildAt(0)
var offset: Int? = null
var isDown: Boolean? = if (firstVisibleItem == lastItemPosition || lastItemPosition == -1) null else firstVisibleItem > lastItemPosition
val dividerHeight = if (lv is ListView) lv.dividerHeight else 0
val columnCount = if (lv is GridView) lv.numColumns else 1
if (child != null) {
if (lastItemPosition != -1) {
when (firstVisibleItem - lastItemPosition) {
0 -> {
isDown = if (lastItemTop == child.top) null else lastItemTop!! > child.top
offset = Math.abs(lastItemTop!! - child.top)
}
columnCount -> offset = lastItemHeight!! + lastItemTop!! - child.top + dividerHeight
-columnCount -> offset = child.height + child.top - lastItemTop!! + dividerHeight
}
}
lastItemPosition = firstVisibleItem
lastItemHeight = child.height
lastItemTop = child.top
if (isDown != null && (offset == null || offset != 0)
&& lastScrollState != AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
onTouchScrollListener(isDown, offset, true)
}
}
}
override fun onScrollStateChanged(view: AbsListView, scrollState: Int) {
lastScrollState = scrollState
if (scrollState == AbsListView.OnScrollListener.SCROLL_STATE_IDLE) {
onTouchScrollListener(true, 0, false)
lastItemPosition = -1
lastItemHeight = null
lastItemTop = null
}
}
})
}
Ensuite, nous pouvons utiliser quand une liste est défilée au-delà du seuil
private var lastThresholdOffset = 0
private var thresholdHeight = some value
setOnTouchScrollListener(listView) { isDown: Boolean, offset: Int?, isScrollWorking: Boolean ->
val offset = offset ?: if (isDown) 0 else thresholdHeight
lastThresholdOffset = if (isDown) Math.min(thresholdHeight, lastThresholdOffset + offset)
else Math.max(0, lastThresholdOffset - offset)
val result = lastThresholdOffset > thresholdHeight
}
isScrollWorking - peut être utilisé pour une animation
Un code de refactor de la réponse de Malachiasz. Cette fonction est utilisée pour la hauteur de ligne dynamique.
Appeler l'auditeur onScroll
mListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
if (mCardsListView.getChildCount() > 0) {
int scrollY = getScrollY();
}
}
});
fonction getScrollY
private Dictionary<Integer, Integer> mListViewItemHeights = new Hashtable<Integer, Integer>();
private int getScrollY() {
View child = mCardsListView.getChildAt(0); //this is the first visible row
if (child == null) return 0;
int scrollY = -child.getTop();
mListViewItemHeights.put(mCardsListView.getFirstVisiblePosition(), child.getHeight());
for (int i = 0; i < mCardsListView.getFirstVisiblePosition(); ++i) {
Integer hei = mListViewItemHeights.get(i);
//Manual add hei each row into scrollY
if (hei != null)
scrollY += hei;
}
return scrollY;
}
Vous pouvez essayer d'implémenter OnTouchListener
et remplacer sa onTouch(View v, MotionEvent event)
et obtenir x et y en utilisant event.getX()
et event.getY()
. Je venais de créer une démo à balayer sur la ligne ListView qui activera un bouton de suppression permettant de supprimer un élément particulier de ListView. Vous pouvez vérifier le code source de mon github en tant que ListItemSwipe
.