J'ai un ScrollView qui entoure toute ma mise en page afin que tout l'écran puisse défiler. Le premier élément que j'ai dans ce ScrollView est un bloc HorizontalScrollView qui a des fonctionnalités qui peuvent être parcourues horizontalement. J'ai ajouté un écouteur d'écoute à la vue de défilement horizontale pour gérer les événements tactiles et forcer la vue à "s'accrochage" à l'image la plus proche sur l'événement ACTION_UP.
L'effet que je recherche est donc comme l'écran d'accueil Android d'origine, où vous pouvez faire défiler de l'un à l'autre et il s'enclenche sur un écran lorsque vous soulevez votre doigt.
Tout cela fonctionne très bien, sauf pour un problème: je dois balayer de gauche à droite presque parfaitement horizontalement pour qu'un ACTION_UP s'enregistre. Si je glisse verticalement à tout le moins (ce que je pense que beaucoup de gens ont tendance à faire sur leur téléphone en balayant d'un côté à l'autre), je recevrai un ACTION_CANCEL au lieu d'un ACTION_UP. Ma théorie est que cela est dû au fait que la vue de défilement horizontal est dans une vue de défilement, et que la vue de défilement détourne le toucher vertical pour permettre le défilement vertical.
Comment puis-je désactiver les événements tactiles pour la vue de défilement à partir de ma vue de défilement horizontale tout en permettant un défilement vertical normal ailleurs dans la vue de défilement?
Voici un exemple de mon code:
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
) ici velir.com/blog/index.php/2010/11/17/… Il y a quelques commentaires supplémentaires sur ce qui se passe pendant que la classe de défilement personnalisée est composée.
MeetMe's HorizontalListView
bibliothèque.