J'ai un ViewSwitcher
personnalisé dans lequel j'ai implémenté des événements tactiles afin que je puisse parcourir les écrans à l'aide de l'écran tactile.
Ma hiérarchie de présentation ressemble à ceci:
<ViewSwitcher>
<LinearLayout>
<ListView />
</LinearLayout>
<LinearLayout>
<ListView />
</LinearLayout>
</ViewSwitcher>
Maintenant, le problème est que les événements tactiles sont consommés par le ListViews
et je ne suis pas en mesure de changer de vue. Cela fonctionne bien quand je n'ai pas le ListViews
. Je dois pouvoir faire défiler les vues Et faire défiler la ListView
.
Comment résoudre ce problème?
EDIT: J'ai également besoin des éléments ListView
pour pouvoir être cliqués.
Merci d'avance!
Merci à tous d'avoir répondu à la question. Mais j'ai été capable de le comprendre d'une manière beaucoup plus simple. Comme ma ViewSwitcher
ne détectait pas l'événement tactile, j'ai intercepté l'événement tactile, appelé onTouchEvent()
et renvoyé false
. Ici:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
onTouchEvent(ev);
return false;
}
En remplaçant le onInterceptTouchEvent()
, j'ai pu intercepter l'événement tactile de l'activité. Ensuite, j'ai appelé onTouchEvent()
dans la ViewSwitcher
qui gère le basculement de la ListViews
. Et enfin, en renvoyant false
, il s'assure que ViewGroup
ne consomme pas l'événement.
Le moyen le plus simple de passer d'une vue enfant à un événement tactile en vue parent consiste à l'ajouter à la vue enfant:
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
return false;
}
Dans ma présentation parente, le seul moyen que j'ai trouvé pour empêcher l'enfant de capturer l'événement tactile consiste à remplacer onInterceptTouchEvent par true.
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
return true;
}
Je ne pense pas qu'il y ait un moyen facile pour vous de faire cela.
Ce n'est pas si compliqué, mais vous devrez créer votre propre vue qui étend la liste. Ensuite, vous pouvez remplacer le gestionnaire onTouch
et décider (en fonction de l'événement touch) si vous souhaitez le gérer (et renvoyer la valeur true) ou le transmettre à la vue parent.
Le problème est aussi qu'une fois qu'un View gère un événement tactile, c'est celui qui récupérera tous les événements restants ...
À partir de documentation Android :
onTouch () - Ceci renvoie un booléen à indiquez si votre auditeur consomme cet événement. L'important La chose est que cet événement peut avoir plusieurs actions qui suivent chaque autre. Donc, si vous retournez false quand l'événement vers le bas est reçu, vous indique que vous n'avez pas consommé l'événement et ne sont pas non plus intéressés dans les actions ultérieures de cet événement . Ainsi, vous ne serez appelé pour aucun d'autres actions au sein de l'événement, telles que comme un geste du doigt, ou l'éventuel événement d'action
Ainsi, par exemple, si vous souhaitez un déplacement vertical pour faire défiler la liste et au cours du même événement tactile (sans lever le doigt), vous souhaitez un déplacement horizontal pour changer de vue, ce sera assez difficile.
Mais si vous pouvez utiliser des gestes par exemple ou tout gérer dans votre vue personnalisée et, en fonction de ce qu'est MotionEvent, envoyez des commandes à ViewSwitcher.
Vous pouvez également insérer un appel pour gérer touchevent
dans dispatchTouchEvent
, mais dans ce cas, vous devez également remplacer onTouchEvent
pour renvoyer la valeur true, sinon seule la première MotionEvent
DOWN du geste sera transmise.
Voici le conteneur d’emballage tactile:
<?xml version="1.0" encoding="utf-8"?>
<view xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/pager"
Android:layout_width="match_parent"
Android:layout_height="match_parent"
class="com.example.myapp.FragmentContainer$TouchableWrapper" />
Et la classe:
public static class TouchableWrapper extends FrameLayout {
private GestureDetector gestureDetector;
public void setGestureDetector(GestureDetector gestureDetector) {
this.gestureDetector = gestureDetector;
}
// these constructors for the XML inflater
public TouchableWrapper(Context context) {
super(context);
}
public TouchableWrapper(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TouchableWrapper(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent event) {
Log.d(TAG, "onInterceptTouchEvent " + event.toString());
return false; // true for intercept, false è default and pass on to children View
}
@Override
public boolean dispatchTouchEvent(MotionEvent event) {
Log.d(TAG, "dispatchTouchEvent " + event.toString());
gestureDetector.onTouchEvent(event);
return super.dispatchTouchEvent(event);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.d(TAG, "onTouchEvent " + event.toString());
return true; //return super.onTouchEvent(event);
}
}
Ceci est la référence GestureDetector
:
private GestureDetector gestureDetector;
C'est la GestureListener
:
private GestureDetector.SimpleOnGestureListener sOGL = new GestureDetector.SimpleOnGestureListener() {
private static final int SWIPE_THRESHOLD = 100;
private static final int SWIPE_VELOCITY_THRESHOLD = 100;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
goToRight(); // onSwipeRight();
} else {
goToLeft(); // onSwipeLeft();
}
}
result = true;
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
// onSwipeBottom();
} else {
// onSwipeTop();
}
}
result = true;
} catch (Exception exception) {
exception.printStackTrace();
}
return result; // return false indicate event not handled
}
};
Ceci pour charger le fragment de conteneur pouvant être touché et un fragment contenu:
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log.d(TAG, "onCreateView()");
View view = inflater.inflate(R.layout.fragmentcontainer, container, false);
gestureDetector = new GestureDetector(view.getContext(), sOGL);
((FragmentContainer.TouchableWrapper) view).setGestureDetector(gestureDetector);
FragmentManager fm = this.getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.pager, frag).commit();
return view;
}
Si votre vue veut faire passer l'événement, assurez-vous de renvoyer false dans onTouchEvent. Sinon, la plate-forme pense que vous avez consommé l'événement et aucun traitement supplémentaire n'est nécessaire.
ce que j’ai fait est de définir un contactventlistener sur la liste dans le viewwitcher, gère l’événement, détecte l’action fling et appelle le metchod de viewswitcher. Ça marche.
Il était nécessaire de manipuler le toucher dans TextView dans la vue parent avec autoLink = "trois"
private LinearLayout mParentView;
private TextView mTextView;
private View.OnTouchListener mParentListener = new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
......
return false;
}
};
mParentView.setOnTouchListener(mParentListener);
mTextView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
mParentListener.onTouch(mParentView, event);
return false;
}
};
Avez-vous essayé de définir les éléments de liste comme non-cliquables comme ceci: Cela devrait propager l'événement click vers le haut.