Ho un ScrollView che circonda il mio intero layout in modo che l'intero schermo sia scorrevole. Il primo elemento che ho in questo ScrollView è un blocco HorizontalScrollView che ha funzionalità che possono essere fatte scorrere orizzontalmente. Ho aggiunto un intouchlistener alla visualizzazione orizzontale per gestire gli eventi touch e forzare la vista a "scattare" sull'immagine più vicina all'evento ACTION_UP.
Quindi l'effetto che sto cercando è come la schermata iniziale di Android in cui è possibile scorrere da uno all'altro e scatta su uno schermo quando si solleva il dito.
Tutto funziona alla grande, tranne per un problema: ho bisogno di scorrere da sinistra a destra quasi perfettamente in orizzontale affinché un ACTION_UP possa registrarsi. Se scorro per lo meno verticalmente (cosa che penso che molte persone tendano a fare sui loro telefoni quando passano da una parte all'altra), riceverò un ACTION_CANCEL invece di un ACTION_UP. La mia teoria è che ciò avviene perché la vista orizzontale è all'interno di una vista di scorrimento e la vista di scorrimento dirotta il tocco verticale per consentire lo scorrimento verticale.
Come posso disabilitare gli eventi tattili per la vista di scorrimento appena all'interno della mia vista di scorrimento orizzontale, ma consentire comunque il normale scorrimento verticale altrove nella vista di scorrimento?
Ecco un esempio del mio codice:
public class HomeFeatureLayout extends HorizontalScrollView {
private ArrayList<ListItem> items = null;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
private static final int SWIPE_MIN_DISTANCE = 5;
private static final int SWIPE_THRESHOLD_VELOCITY = 300;
private int activeFeature = 0;
public HomeFeatureLayout(Context context, ArrayList<ListItem> items){
super(context);
setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
setFadingEdgeLength(0);
this.setHorizontalScrollBarEnabled(false);
this.setVerticalScrollBarEnabled(false);
LinearLayout internalWrapper = new LinearLayout(context);
internalWrapper.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
internalWrapper.setOrientation(LinearLayout.HORIZONTAL);
addView(internalWrapper);
this.items = items;
for(int i = 0; i< items.size();i++){
LinearLayout featureLayout = (LinearLayout) View.inflate(this.getContext(),R.layout.homefeature,null);
TextView header = (TextView) featureLayout.findViewById(R.id.featureheader);
ImageView image = (ImageView) featureLayout.findViewById(R.id.featureimage);
TextView title = (TextView) featureLayout.findViewById(R.id.featuretitle);
title.setTag(items.get(i).GetLinkURL());
TextView date = (TextView) featureLayout.findViewById(R.id.featuredate);
header.setText("FEATURED");
Image cachedImage = new Image(this.getContext(), items.get(i).GetImageURL());
image.setImageDrawable(cachedImage.getImage());
title.setText(items.get(i).GetTitle());
date.setText(items.get(i).GetDate());
internalWrapper.addView(featureLayout);
}
gestureDetector = new GestureDetector(new MyGestureDetector());
setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (gestureDetector.onTouchEvent(event)) {
return true;
}
else if(event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL ){
int scrollX = getScrollX();
int featureWidth = getMeasuredWidth();
activeFeature = ((scrollX + (featureWidth/2))/featureWidth);
int scrollTo = activeFeature*featureWidth;
smoothScrollTo(scrollTo, 0);
return true;
}
else{
return false;
}
}
});
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
//right to left
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
activeFeature = (activeFeature < (items.size() - 1))? activeFeature + 1:items.size() -1;
smoothScrollTo(activeFeature*getMeasuredWidth(), 0);
return true;
}
//left to right
else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
activeFeature = (activeFeature > 0)? activeFeature - 1:0;
smoothScrollTo(activeFeature*getMeasuredWidth(), 0);
return true;
}
} catch (Exception e) {
// nothing
}
return false;
}
}
}
HomeFeatureLayout extends HorizontalScrollView
) qui velir.com/blog/index.php/2010/11/17/… Ci sono alcuni commenti aggiuntivi su ciò che sta accadendo mentre la classe di scorrimento personalizzata è composta.
MeetMe's HorizontalListView
biblioteca.